mirror of
https://github.com/mattermost/focalboard.git
synced 2024-11-27 08:31:20 +02:00
Person Property Type (#406)
* Added getWorkspaceUsers API * Integrated workspace user API in UI * Integrated workspace user API in UI * Added toto for implementation slot * Implemenmted getWorkspaceUSers to get data from Focalboard DB * Updated store mocks * Made select styles a shared constant * Removed unwanted diffs * Removed unwanted diffs * Updated snapshots for new property type * Added user store test * Added missing copyright notice * Returning error if no users found to retain original behavior * Minor fixes and added tests * Minor fixes * Used React context for workspace users * Used useContext hook, and added additional user ID -> user context to avoid that computation by all componnets * Mergerd both workspace user contextx * Minor review fix
This commit is contained in:
parent
b45c1e7fd0
commit
90f6389745
@ -71,6 +71,7 @@ func (a *API) RegisterRoutes(r *mux.Router) {
|
|||||||
|
|
||||||
apiv1.HandleFunc("/workspaces/{workspaceID}", a.sessionRequired(a.handleGetWorkspace)).Methods("GET")
|
apiv1.HandleFunc("/workspaces/{workspaceID}", a.sessionRequired(a.handleGetWorkspace)).Methods("GET")
|
||||||
apiv1.HandleFunc("/workspaces/{workspaceID}/regenerate_signup_token", a.sessionRequired(a.handlePostWorkspaceRegenerateSignupToken)).Methods("POST")
|
apiv1.HandleFunc("/workspaces/{workspaceID}/regenerate_signup_token", a.sessionRequired(a.handlePostWorkspaceRegenerateSignupToken)).Methods("POST")
|
||||||
|
apiv1.HandleFunc("/workspaces/{workspaceID}/users", a.sessionRequired(a.getWorkspaceUsers)).Methods("GET")
|
||||||
|
|
||||||
// User APIs
|
// User APIs
|
||||||
apiv1.HandleFunc("/users/me", a.sessionRequired(a.handleGetMe)).Methods("GET")
|
apiv1.HandleFunc("/users/me", a.sessionRequired(a.handleGetMe)).Methods("GET")
|
||||||
@ -1133,6 +1134,59 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
jsonBytesResponse(w, http.StatusOK, data)
|
jsonBytesResponse(w, http.StatusOK, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) getWorkspaceUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// swagger:operation GET /api/v1/workspaces/{workspaceID}/users getWorkspaceUsers
|
||||||
|
//
|
||||||
|
// Returns workspace users
|
||||||
|
//
|
||||||
|
// ---
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: workspaceID
|
||||||
|
// in: path
|
||||||
|
// description: Workspace ID
|
||||||
|
// required: true
|
||||||
|
// type: string
|
||||||
|
// security:
|
||||||
|
// - BearerAuth: []
|
||||||
|
// responses:
|
||||||
|
// '200':
|
||||||
|
// description: success
|
||||||
|
// schema:
|
||||||
|
// type: array
|
||||||
|
// items:
|
||||||
|
// "$ref": "#/definitions/User"
|
||||||
|
// default:
|
||||||
|
// description: internal error
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/ErrorResponse"
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
workspaceID := vars["workspaceID"]
|
||||||
|
|
||||||
|
ctx := r.Context()
|
||||||
|
session := ctx.Value("session").(*model.Session)
|
||||||
|
if !a.app().DoesUserHaveWorkspaceAccess(session.UserID, workspaceID) {
|
||||||
|
a.errorResponse(w, http.StatusForbidden, "Access denied to workspace", errors.New("Access denied to workspace"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
users, err := a.app().GetWorkspaceUsers(workspaceID)
|
||||||
|
if err != nil {
|
||||||
|
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(users)
|
||||||
|
if err != nil {
|
||||||
|
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonBytesResponse(w, http.StatusOK, data)
|
||||||
|
}
|
||||||
|
|
||||||
// Response helpers
|
// Response helpers
|
||||||
|
|
||||||
func (a *API) errorResponse(w http.ResponseWriter, code int, message string, sourceError error) {
|
func (a *API) errorResponse(w http.ResponseWriter, code int, message string, sourceError error) {
|
||||||
|
7
server/app/user.go
Normal file
7
server/app/user.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import "github.com/mattermost/focalboard/server/model"
|
||||||
|
|
||||||
|
func (a *App) GetWorkspaceUsers(workspaceID string) ([]*model.User, error) {
|
||||||
|
return a.store.GetUsersByWorkspace(workspaceID)
|
||||||
|
}
|
@ -27,6 +27,7 @@ require (
|
|||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/tidwall/gjson v1.7.3 // indirect
|
github.com/tidwall/gjson v1.7.3 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 // indirect
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
)
|
)
|
||||||
|
@ -1183,6 +1183,7 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
|
|||||||
golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -1381,6 +1382,7 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
|||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
@ -36,133 +36,133 @@ func (m *MockStore) EXPECT() *MockStoreMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CleanUpSessions mocks base method.
|
// CleanUpSessions mocks base method.
|
||||||
func (m *MockStore) CleanUpSessions(arg0 int64) error {
|
func (m *MockStore) CleanUpSessions(expireTime int64) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CleanUpSessions", arg0)
|
ret := m.ctrl.Call(m, "CleanUpSessions", expireTime)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUpSessions indicates an expected call of CleanUpSessions.
|
// CleanUpSessions indicates an expected call of CleanUpSessions.
|
||||||
func (mr *MockStoreMockRecorder) CleanUpSessions(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) CleanUpSessions(expireTime interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanUpSessions", reflect.TypeOf((*MockStore)(nil).CleanUpSessions), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanUpSessions", reflect.TypeOf((*MockStore)(nil).CleanUpSessions), expireTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSession mocks base method.
|
// CreateSession mocks base method.
|
||||||
func (m *MockStore) CreateSession(arg0 *model.Session) error {
|
func (m *MockStore) CreateSession(session *model.Session) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CreateSession", arg0)
|
ret := m.ctrl.Call(m, "CreateSession", session)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSession indicates an expected call of CreateSession.
|
// CreateSession indicates an expected call of CreateSession.
|
||||||
func (mr *MockStoreMockRecorder) CreateSession(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) CreateSession(session interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSession", reflect.TypeOf((*MockStore)(nil).CreateSession), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSession", reflect.TypeOf((*MockStore)(nil).CreateSession), session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUser mocks base method.
|
// CreateUser mocks base method.
|
||||||
func (m *MockStore) CreateUser(arg0 *model.User) error {
|
func (m *MockStore) CreateUser(user *model.User) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CreateUser", arg0)
|
ret := m.ctrl.Call(m, "CreateUser", user)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUser indicates an expected call of CreateUser.
|
// CreateUser indicates an expected call of CreateUser.
|
||||||
func (mr *MockStoreMockRecorder) CreateUser(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) CreateUser(user interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBlock mocks base method.
|
// DeleteBlock mocks base method.
|
||||||
func (m *MockStore) DeleteBlock(arg0 store.Container, arg1, arg2 string) error {
|
func (m *MockStore) DeleteBlock(c store.Container, blockID, modifiedBy string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "DeleteBlock", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "DeleteBlock", c, blockID, modifiedBy)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBlock indicates an expected call of DeleteBlock.
|
// DeleteBlock indicates an expected call of DeleteBlock.
|
||||||
func (mr *MockStoreMockRecorder) DeleteBlock(arg0, arg1, arg2 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) DeleteBlock(c, blockID, modifiedBy interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBlock", reflect.TypeOf((*MockStore)(nil).DeleteBlock), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBlock", reflect.TypeOf((*MockStore)(nil).DeleteBlock), c, blockID, modifiedBy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession mocks base method.
|
// DeleteSession mocks base method.
|
||||||
func (m *MockStore) DeleteSession(arg0 string) error {
|
func (m *MockStore) DeleteSession(sessionId string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "DeleteSession", arg0)
|
ret := m.ctrl.Call(m, "DeleteSession", sessionId)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSession indicates an expected call of DeleteSession.
|
// DeleteSession indicates an expected call of DeleteSession.
|
||||||
func (mr *MockStoreMockRecorder) DeleteSession(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) DeleteSession(sessionId interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSession", reflect.TypeOf((*MockStore)(nil).DeleteSession), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSession", reflect.TypeOf((*MockStore)(nil).DeleteSession), sessionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActiveUserCount mocks base method.
|
// GetActiveUserCount mocks base method.
|
||||||
func (m *MockStore) GetActiveUserCount(arg0 int64) (int, error) {
|
func (m *MockStore) GetActiveUserCount(updatedSecondsAgo int64) (int, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetActiveUserCount", arg0)
|
ret := m.ctrl.Call(m, "GetActiveUserCount", updatedSecondsAgo)
|
||||||
ret0, _ := ret[0].(int)
|
ret0, _ := ret[0].(int)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActiveUserCount indicates an expected call of GetActiveUserCount.
|
// GetActiveUserCount indicates an expected call of GetActiveUserCount.
|
||||||
func (mr *MockStoreMockRecorder) GetActiveUserCount(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetActiveUserCount(updatedSecondsAgo interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActiveUserCount", reflect.TypeOf((*MockStore)(nil).GetActiveUserCount), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActiveUserCount", reflect.TypeOf((*MockStore)(nil).GetActiveUserCount), updatedSecondsAgo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllBlocks mocks base method.
|
// GetAllBlocks mocks base method.
|
||||||
func (m *MockStore) GetAllBlocks(arg0 store.Container) ([]model.Block, error) {
|
func (m *MockStore) GetAllBlocks(c store.Container) ([]model.Block, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetAllBlocks", arg0)
|
ret := m.ctrl.Call(m, "GetAllBlocks", c)
|
||||||
ret0, _ := ret[0].([]model.Block)
|
ret0, _ := ret[0].([]model.Block)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllBlocks indicates an expected call of GetAllBlocks.
|
// GetAllBlocks indicates an expected call of GetAllBlocks.
|
||||||
func (mr *MockStoreMockRecorder) GetAllBlocks(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetAllBlocks(c interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBlocks", reflect.TypeOf((*MockStore)(nil).GetAllBlocks), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBlocks", reflect.TypeOf((*MockStore)(nil).GetAllBlocks), c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithParent mocks base method.
|
// GetBlocksWithParent mocks base method.
|
||||||
func (m *MockStore) GetBlocksWithParent(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
func (m *MockStore) GetBlocksWithParent(c store.Container, parentID string) ([]model.Block, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetBlocksWithParent", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetBlocksWithParent", c, parentID)
|
||||||
ret0, _ := ret[0].([]model.Block)
|
ret0, _ := ret[0].([]model.Block)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithParent indicates an expected call of GetBlocksWithParent.
|
// GetBlocksWithParent indicates an expected call of GetBlocksWithParent.
|
||||||
func (mr *MockStoreMockRecorder) GetBlocksWithParent(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetBlocksWithParent(c, parentID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParent", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParent), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParent", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParent), c, parentID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithParentAndType mocks base method.
|
// GetBlocksWithParentAndType mocks base method.
|
||||||
func (m *MockStore) GetBlocksWithParentAndType(arg0 store.Container, arg1, arg2 string) ([]model.Block, error) {
|
func (m *MockStore) GetBlocksWithParentAndType(c store.Container, parentID, blockType string) ([]model.Block, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetBlocksWithParentAndType", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "GetBlocksWithParentAndType", c, parentID, blockType)
|
||||||
ret0, _ := ret[0].([]model.Block)
|
ret0, _ := ret[0].([]model.Block)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithParentAndType indicates an expected call of GetBlocksWithParentAndType.
|
// GetBlocksWithParentAndType indicates an expected call of GetBlocksWithParentAndType.
|
||||||
func (mr *MockStoreMockRecorder) GetBlocksWithParentAndType(arg0, arg1, arg2 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetBlocksWithParentAndType(c, parentID, blockType interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParentAndType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParentAndType), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParentAndType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParentAndType), c, parentID, blockType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithRootID mocks base method.
|
// GetBlocksWithRootID mocks base method.
|
||||||
@ -181,33 +181,33 @@ func (mr *MockStoreMockRecorder) GetBlocksWithRootID(arg0, arg1 interface{}) *go
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithType mocks base method.
|
// GetBlocksWithType mocks base method.
|
||||||
func (m *MockStore) GetBlocksWithType(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
func (m *MockStore) GetBlocksWithType(c store.Container, blockType string) ([]model.Block, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetBlocksWithType", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetBlocksWithType", c, blockType)
|
||||||
ret0, _ := ret[0].([]model.Block)
|
ret0, _ := ret[0].([]model.Block)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocksWithType indicates an expected call of GetBlocksWithType.
|
// GetBlocksWithType indicates an expected call of GetBlocksWithType.
|
||||||
func (mr *MockStoreMockRecorder) GetBlocksWithType(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetBlocksWithType(c, blockType interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithType), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithType), c, blockType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParentID mocks base method.
|
// GetParentID mocks base method.
|
||||||
func (m *MockStore) GetParentID(arg0 store.Container, arg1 string) (string, error) {
|
func (m *MockStore) GetParentID(c store.Container, blockID string) (string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetParentID", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetParentID", c, blockID)
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(string)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParentID indicates an expected call of GetParentID.
|
// GetParentID indicates an expected call of GetParentID.
|
||||||
func (mr *MockStoreMockRecorder) GetParentID(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetParentID(c, blockID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParentID", reflect.TypeOf((*MockStore)(nil).GetParentID), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParentID", reflect.TypeOf((*MockStore)(nil).GetParentID), c, blockID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRegisteredUserCount mocks base method.
|
// GetRegisteredUserCount mocks base method.
|
||||||
@ -226,78 +226,78 @@ func (mr *MockStoreMockRecorder) GetRegisteredUserCount() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetRootID mocks base method.
|
// GetRootID mocks base method.
|
||||||
func (m *MockStore) GetRootID(arg0 store.Container, arg1 string) (string, error) {
|
func (m *MockStore) GetRootID(c store.Container, blockID string) (string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetRootID", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetRootID", c, blockID)
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(string)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootID indicates an expected call of GetRootID.
|
// GetRootID indicates an expected call of GetRootID.
|
||||||
func (mr *MockStoreMockRecorder) GetRootID(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetRootID(c, blockID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRootID", reflect.TypeOf((*MockStore)(nil).GetRootID), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRootID", reflect.TypeOf((*MockStore)(nil).GetRootID), c, blockID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSession mocks base method.
|
// GetSession mocks base method.
|
||||||
func (m *MockStore) GetSession(arg0 string, arg1 int64) (*model.Session, error) {
|
func (m *MockStore) GetSession(token string, expireTime int64) (*model.Session, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetSession", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetSession", token, expireTime)
|
||||||
ret0, _ := ret[0].(*model.Session)
|
ret0, _ := ret[0].(*model.Session)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSession indicates an expected call of GetSession.
|
// GetSession indicates an expected call of GetSession.
|
||||||
func (mr *MockStoreMockRecorder) GetSession(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetSession(token, expireTime interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSession", reflect.TypeOf((*MockStore)(nil).GetSession), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSession", reflect.TypeOf((*MockStore)(nil).GetSession), token, expireTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSharing mocks base method.
|
// GetSharing mocks base method.
|
||||||
func (m *MockStore) GetSharing(arg0 store.Container, arg1 string) (*model.Sharing, error) {
|
func (m *MockStore) GetSharing(c store.Container, rootID string) (*model.Sharing, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetSharing", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetSharing", c, rootID)
|
||||||
ret0, _ := ret[0].(*model.Sharing)
|
ret0, _ := ret[0].(*model.Sharing)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSharing indicates an expected call of GetSharing.
|
// GetSharing indicates an expected call of GetSharing.
|
||||||
func (mr *MockStoreMockRecorder) GetSharing(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetSharing(c, rootID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSharing", reflect.TypeOf((*MockStore)(nil).GetSharing), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSharing", reflect.TypeOf((*MockStore)(nil).GetSharing), c, rootID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSubTree2 mocks base method.
|
// GetSubTree2 mocks base method.
|
||||||
func (m *MockStore) GetSubTree2(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
func (m *MockStore) GetSubTree2(c store.Container, blockID string) ([]model.Block, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetSubTree2", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetSubTree2", c, blockID)
|
||||||
ret0, _ := ret[0].([]model.Block)
|
ret0, _ := ret[0].([]model.Block)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSubTree2 indicates an expected call of GetSubTree2.
|
// GetSubTree2 indicates an expected call of GetSubTree2.
|
||||||
func (mr *MockStoreMockRecorder) GetSubTree2(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetSubTree2(c, blockID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree2", reflect.TypeOf((*MockStore)(nil).GetSubTree2), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree2", reflect.TypeOf((*MockStore)(nil).GetSubTree2), c, blockID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSubTree3 mocks base method.
|
// GetSubTree3 mocks base method.
|
||||||
func (m *MockStore) GetSubTree3(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
func (m *MockStore) GetSubTree3(c store.Container, blockID string) ([]model.Block, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetSubTree3", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetSubTree3", c, blockID)
|
||||||
ret0, _ := ret[0].([]model.Block)
|
ret0, _ := ret[0].([]model.Block)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSubTree3 indicates an expected call of GetSubTree3.
|
// GetSubTree3 indicates an expected call of GetSubTree3.
|
||||||
func (mr *MockStoreMockRecorder) GetSubTree3(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetSubTree3(c, blockID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree3", reflect.TypeOf((*MockStore)(nil).GetSubTree3), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree3", reflect.TypeOf((*MockStore)(nil).GetSubTree3), c, blockID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSystemSettings mocks base method.
|
// GetSystemSettings mocks base method.
|
||||||
@ -316,63 +316,78 @@ func (mr *MockStoreMockRecorder) GetSystemSettings() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail mocks base method.
|
// GetUserByEmail mocks base method.
|
||||||
func (m *MockStore) GetUserByEmail(arg0 string) (*model.User, error) {
|
func (m *MockStore) GetUserByEmail(email string) (*model.User, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetUserByEmail", arg0)
|
ret := m.ctrl.Call(m, "GetUserByEmail", email)
|
||||||
ret0, _ := ret[0].(*model.User)
|
ret0, _ := ret[0].(*model.User)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail indicates an expected call of GetUserByEmail.
|
// GetUserByEmail indicates an expected call of GetUserByEmail.
|
||||||
func (mr *MockStoreMockRecorder) GetUserByEmail(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetUserByEmail(email interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByEmail", reflect.TypeOf((*MockStore)(nil).GetUserByEmail), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByEmail", reflect.TypeOf((*MockStore)(nil).GetUserByEmail), email)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserById mocks base method.
|
// GetUserById mocks base method.
|
||||||
func (m *MockStore) GetUserById(arg0 string) (*model.User, error) {
|
func (m *MockStore) GetUserById(userID string) (*model.User, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetUserById", arg0)
|
ret := m.ctrl.Call(m, "GetUserById", userID)
|
||||||
ret0, _ := ret[0].(*model.User)
|
ret0, _ := ret[0].(*model.User)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserById indicates an expected call of GetUserById.
|
// GetUserById indicates an expected call of GetUserById.
|
||||||
func (mr *MockStoreMockRecorder) GetUserById(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetUserById(userID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserById", reflect.TypeOf((*MockStore)(nil).GetUserById), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserById", reflect.TypeOf((*MockStore)(nil).GetUserById), userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByUsername mocks base method.
|
// GetUserByUsername mocks base method.
|
||||||
func (m *MockStore) GetUserByUsername(arg0 string) (*model.User, error) {
|
func (m *MockStore) GetUserByUsername(username string) (*model.User, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetUserByUsername", arg0)
|
ret := m.ctrl.Call(m, "GetUserByUsername", username)
|
||||||
ret0, _ := ret[0].(*model.User)
|
ret0, _ := ret[0].(*model.User)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByUsername indicates an expected call of GetUserByUsername.
|
// GetUserByUsername indicates an expected call of GetUserByUsername.
|
||||||
func (mr *MockStoreMockRecorder) GetUserByUsername(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetUserByUsername(username interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByUsername", reflect.TypeOf((*MockStore)(nil).GetUserByUsername), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByUsername", reflect.TypeOf((*MockStore)(nil).GetUserByUsername), username)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsersByWorkspace mocks base method.
|
||||||
|
func (m *MockStore) GetUsersByWorkspace(workspaceID string) ([]*model.User, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetUsersByWorkspace", workspaceID)
|
||||||
|
ret0, _ := ret[0].([]*model.User)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsersByWorkspace indicates an expected call of GetUsersByWorkspace.
|
||||||
|
func (mr *MockStoreMockRecorder) GetUsersByWorkspace(workspaceID interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersByWorkspace", reflect.TypeOf((*MockStore)(nil).GetUsersByWorkspace), workspaceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWorkspace mocks base method.
|
// GetWorkspace mocks base method.
|
||||||
func (m *MockStore) GetWorkspace(arg0 string) (*model.Workspace, error) {
|
func (m *MockStore) GetWorkspace(ID string) (*model.Workspace, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetWorkspace", arg0)
|
ret := m.ctrl.Call(m, "GetWorkspace", ID)
|
||||||
ret0, _ := ret[0].(*model.Workspace)
|
ret0, _ := ret[0].(*model.Workspace)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWorkspace indicates an expected call of GetWorkspace.
|
// GetWorkspace indicates an expected call of GetWorkspace.
|
||||||
func (mr *MockStoreMockRecorder) GetWorkspace(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetWorkspace(ID interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkspace", reflect.TypeOf((*MockStore)(nil).GetWorkspace), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkspace", reflect.TypeOf((*MockStore)(nil).GetWorkspace), ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasWorkspaceAccess mocks base method.
|
// HasWorkspaceAccess mocks base method.
|
||||||
@ -391,45 +406,45 @@ func (mr *MockStoreMockRecorder) HasWorkspaceAccess(arg0, arg1 interface{}) *gom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertBlock mocks base method.
|
// InsertBlock mocks base method.
|
||||||
func (m *MockStore) InsertBlock(arg0 store.Container, arg1 model.Block) error {
|
func (m *MockStore) InsertBlock(c store.Container, block model.Block) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "InsertBlock", arg0, arg1)
|
ret := m.ctrl.Call(m, "InsertBlock", c, block)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertBlock indicates an expected call of InsertBlock.
|
// InsertBlock indicates an expected call of InsertBlock.
|
||||||
func (mr *MockStoreMockRecorder) InsertBlock(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) InsertBlock(c, block interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertBlock", reflect.TypeOf((*MockStore)(nil).InsertBlock), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertBlock", reflect.TypeOf((*MockStore)(nil).InsertBlock), c, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshSession mocks base method.
|
// RefreshSession mocks base method.
|
||||||
func (m *MockStore) RefreshSession(arg0 *model.Session) error {
|
func (m *MockStore) RefreshSession(session *model.Session) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "RefreshSession", arg0)
|
ret := m.ctrl.Call(m, "RefreshSession", session)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshSession indicates an expected call of RefreshSession.
|
// RefreshSession indicates an expected call of RefreshSession.
|
||||||
func (mr *MockStoreMockRecorder) RefreshSession(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) RefreshSession(session interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RefreshSession", reflect.TypeOf((*MockStore)(nil).RefreshSession), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RefreshSession", reflect.TypeOf((*MockStore)(nil).RefreshSession), session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSystemSetting mocks base method.
|
// SetSystemSetting mocks base method.
|
||||||
func (m *MockStore) SetSystemSetting(arg0, arg1 string) error {
|
func (m *MockStore) SetSystemSetting(key, value string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "SetSystemSetting", arg0, arg1)
|
ret := m.ctrl.Call(m, "SetSystemSetting", key, value)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSystemSetting indicates an expected call of SetSystemSetting.
|
// SetSystemSetting indicates an expected call of SetSystemSetting.
|
||||||
func (mr *MockStoreMockRecorder) SetSystemSetting(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) SetSystemSetting(key, value interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSystemSetting", reflect.TypeOf((*MockStore)(nil).SetSystemSetting), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSystemSetting", reflect.TypeOf((*MockStore)(nil).SetSystemSetting), key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown mocks base method.
|
// Shutdown mocks base method.
|
||||||
@ -447,99 +462,99 @@ func (mr *MockStoreMockRecorder) Shutdown() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSession mocks base method.
|
// UpdateSession mocks base method.
|
||||||
func (m *MockStore) UpdateSession(arg0 *model.Session) error {
|
func (m *MockStore) UpdateSession(session *model.Session) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpdateSession", arg0)
|
ret := m.ctrl.Call(m, "UpdateSession", session)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSession indicates an expected call of UpdateSession.
|
// UpdateSession indicates an expected call of UpdateSession.
|
||||||
func (mr *MockStoreMockRecorder) UpdateSession(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpdateSession(session interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSession", reflect.TypeOf((*MockStore)(nil).UpdateSession), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSession", reflect.TypeOf((*MockStore)(nil).UpdateSession), session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser mocks base method.
|
// UpdateUser mocks base method.
|
||||||
func (m *MockStore) UpdateUser(arg0 *model.User) error {
|
func (m *MockStore) UpdateUser(user *model.User) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpdateUser", arg0)
|
ret := m.ctrl.Call(m, "UpdateUser", user)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser indicates an expected call of UpdateUser.
|
// UpdateUser indicates an expected call of UpdateUser.
|
||||||
func (mr *MockStoreMockRecorder) UpdateUser(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpdateUser(user interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUser", reflect.TypeOf((*MockStore)(nil).UpdateUser), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUser", reflect.TypeOf((*MockStore)(nil).UpdateUser), user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserPassword mocks base method.
|
// UpdateUserPassword mocks base method.
|
||||||
func (m *MockStore) UpdateUserPassword(arg0, arg1 string) error {
|
func (m *MockStore) UpdateUserPassword(username, password string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpdateUserPassword", arg0, arg1)
|
ret := m.ctrl.Call(m, "UpdateUserPassword", username, password)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserPassword indicates an expected call of UpdateUserPassword.
|
// UpdateUserPassword indicates an expected call of UpdateUserPassword.
|
||||||
func (mr *MockStoreMockRecorder) UpdateUserPassword(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpdateUserPassword(username, password interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPassword", reflect.TypeOf((*MockStore)(nil).UpdateUserPassword), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPassword", reflect.TypeOf((*MockStore)(nil).UpdateUserPassword), username, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserPasswordByID mocks base method.
|
// UpdateUserPasswordByID mocks base method.
|
||||||
func (m *MockStore) UpdateUserPasswordByID(arg0, arg1 string) error {
|
func (m *MockStore) UpdateUserPasswordByID(userID, password string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpdateUserPasswordByID", arg0, arg1)
|
ret := m.ctrl.Call(m, "UpdateUserPasswordByID", userID, password)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserPasswordByID indicates an expected call of UpdateUserPasswordByID.
|
// UpdateUserPasswordByID indicates an expected call of UpdateUserPasswordByID.
|
||||||
func (mr *MockStoreMockRecorder) UpdateUserPasswordByID(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpdateUserPasswordByID(userID, password interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPasswordByID", reflect.TypeOf((*MockStore)(nil).UpdateUserPasswordByID), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPasswordByID", reflect.TypeOf((*MockStore)(nil).UpdateUserPasswordByID), userID, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpsertSharing mocks base method.
|
// UpsertSharing mocks base method.
|
||||||
func (m *MockStore) UpsertSharing(arg0 store.Container, arg1 model.Sharing) error {
|
func (m *MockStore) UpsertSharing(c store.Container, sharing model.Sharing) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpsertSharing", arg0, arg1)
|
ret := m.ctrl.Call(m, "UpsertSharing", c, sharing)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpsertSharing indicates an expected call of UpsertSharing.
|
// UpsertSharing indicates an expected call of UpsertSharing.
|
||||||
func (mr *MockStoreMockRecorder) UpsertSharing(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpsertSharing(c, sharing interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertSharing", reflect.TypeOf((*MockStore)(nil).UpsertSharing), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertSharing", reflect.TypeOf((*MockStore)(nil).UpsertSharing), c, sharing)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpsertWorkspaceSettings mocks base method.
|
// UpsertWorkspaceSettings mocks base method.
|
||||||
func (m *MockStore) UpsertWorkspaceSettings(arg0 model.Workspace) error {
|
func (m *MockStore) UpsertWorkspaceSettings(workspace model.Workspace) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpsertWorkspaceSettings", arg0)
|
ret := m.ctrl.Call(m, "UpsertWorkspaceSettings", workspace)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpsertWorkspaceSettings indicates an expected call of UpsertWorkspaceSettings.
|
// UpsertWorkspaceSettings indicates an expected call of UpsertWorkspaceSettings.
|
||||||
func (mr *MockStoreMockRecorder) UpsertWorkspaceSettings(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpsertWorkspaceSettings(workspace interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertWorkspaceSettings", reflect.TypeOf((*MockStore)(nil).UpsertWorkspaceSettings), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertWorkspaceSettings", reflect.TypeOf((*MockStore)(nil).UpsertWorkspaceSettings), workspace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpsertWorkspaceSignupToken mocks base method.
|
// UpsertWorkspaceSignupToken mocks base method.
|
||||||
func (m *MockStore) UpsertWorkspaceSignupToken(arg0 model.Workspace) error {
|
func (m *MockStore) UpsertWorkspaceSignupToken(workspace model.Workspace) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "UpsertWorkspaceSignupToken", arg0)
|
ret := m.ctrl.Call(m, "UpsertWorkspaceSignupToken", workspace)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpsertWorkspaceSignupToken indicates an expected call of UpsertWorkspaceSignupToken.
|
// UpsertWorkspaceSignupToken indicates an expected call of UpsertWorkspaceSignupToken.
|
||||||
func (mr *MockStoreMockRecorder) UpsertWorkspaceSignupToken(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) UpsertWorkspaceSignupToken(workspace interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertWorkspaceSignupToken", reflect.TypeOf((*MockStore)(nil).UpsertWorkspaceSignupToken), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertWorkspaceSignupToken", reflect.TypeOf((*MockStore)(nil).UpsertWorkspaceSignupToken), workspace)
|
||||||
}
|
}
|
||||||
|
@ -39,4 +39,5 @@ func TestBlocksStore(t *testing.T) {
|
|||||||
t.Run("BlocksStore", func(t *testing.T) { storetests.StoreTestBlocksStore(t, SetupTests) })
|
t.Run("BlocksStore", func(t *testing.T) { storetests.StoreTestBlocksStore(t, SetupTests) })
|
||||||
t.Run("SharingStore", func(t *testing.T) { storetests.StoreTestSharingStore(t, SetupTests) })
|
t.Run("SharingStore", func(t *testing.T) { storetests.StoreTestSharingStore(t, SetupTests) })
|
||||||
t.Run("SystemStore", func(t *testing.T) { storetests.StoreTestSystemStore(t, SetupTests) })
|
t.Run("SystemStore", func(t *testing.T) { storetests.StoreTestSystemStore(t, SetupTests) })
|
||||||
|
t.Run("UserStore", func(t *testing.T) { storetests.StoreTestUserStore(t, SetupTests) })
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package sqlstore
|
package sqlstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattermost/focalboard/server/model"
|
"github.com/mattermost/focalboard/server/model"
|
||||||
@ -27,26 +29,52 @@ func (s *SQLStore) GetRegisteredUserCount() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLStore) getUserByCondition(condition sq.Eq) (*model.User, error) {
|
func (s *SQLStore) getUserByCondition(condition sq.Eq) (*model.User, error) {
|
||||||
|
users, err := s.getUsersByCondition(condition)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(users) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return users[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SQLStore) getUsersByCondition(condition sq.Eq) ([]*model.User, error) {
|
||||||
query := s.getQueryBuilder().
|
query := s.getQueryBuilder().
|
||||||
Select("id", "username", "email", "password", "mfa_secret", "auth_service", "auth_data", "props", "create_at", "update_at", "delete_at").
|
Select(
|
||||||
|
"id",
|
||||||
|
"username",
|
||||||
|
"email",
|
||||||
|
"password",
|
||||||
|
"mfa_secret",
|
||||||
|
"auth_service",
|
||||||
|
"auth_data",
|
||||||
|
"props",
|
||||||
|
"create_at",
|
||||||
|
"update_at",
|
||||||
|
"delete_at",
|
||||||
|
).
|
||||||
From(s.tablePrefix + "users").
|
From(s.tablePrefix + "users").
|
||||||
Where(sq.Eq{"delete_at": 0}).
|
Where(sq.Eq{"delete_at": 0}).
|
||||||
Where(condition)
|
Where(condition)
|
||||||
row := query.QueryRow()
|
rows, err := query.Query()
|
||||||
user := model.User{}
|
if err != nil {
|
||||||
|
log.Printf("getUsersByCondition ERROR: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var propsBytes []byte
|
users, err := s.usersFromRows(rows)
|
||||||
err := row.Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.MfaSecret, &user.AuthService, &user.AuthData, &propsBytes, &user.CreateAt, &user.UpdateAt, &user.DeleteAt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(propsBytes, &user.Props)
|
if len(users) == 0 {
|
||||||
if err != nil {
|
return nil, sql.ErrNoRows
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &user, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLStore) GetUserById(userID string) (*model.User, error) {
|
func (s *SQLStore) GetUserById(userID string) (*model.User, error) {
|
||||||
@ -158,3 +186,44 @@ func (s *SQLStore) UpdateUserPasswordByID(userID, password string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SQLStore) GetUsersByWorkspace(workspaceID string) ([]*model.User, error) {
|
||||||
|
return s.getUsersByCondition(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SQLStore) usersFromRows(rows *sql.Rows) ([]*model.User, error) {
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
users := []*model.User{}
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var user model.User
|
||||||
|
var propsBytes []byte
|
||||||
|
|
||||||
|
err := rows.Scan(
|
||||||
|
&user.ID,
|
||||||
|
&user.Username,
|
||||||
|
&user.Email,
|
||||||
|
&user.Password,
|
||||||
|
&user.MfaSecret,
|
||||||
|
&user.AuthService,
|
||||||
|
&user.AuthData,
|
||||||
|
&propsBytes,
|
||||||
|
&user.CreateAt,
|
||||||
|
&user.UpdateAt,
|
||||||
|
&user.DeleteAt,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(propsBytes, &user.Props)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
users = append(users, &user)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users, nil
|
||||||
|
}
|
||||||
|
@ -36,6 +36,7 @@ type Store interface {
|
|||||||
UpdateUser(user *model.User) error
|
UpdateUser(user *model.User) error
|
||||||
UpdateUserPassword(username, password string) error
|
UpdateUserPassword(username, password string) error
|
||||||
UpdateUserPasswordByID(userID, password string) error
|
UpdateUserPasswordByID(userID, password string) error
|
||||||
|
GetUsersByWorkspace(workspaceID string) ([]*model.User, error)
|
||||||
|
|
||||||
GetActiveUserCount(updatedSecondsAgo int64) (int, error)
|
GetActiveUserCount(updatedSecondsAgo int64) (int, error)
|
||||||
GetSession(token string, expireTime int64) (*model.Session, error)
|
GetSession(token string, expireTime int64) (*model.Session, error)
|
||||||
|
52
server/services/store/storetests/users.go
Normal file
52
server/services/store/storetests/users.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package storetests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/mattermost/focalboard/server/model"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/mattermost/focalboard/server/services/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StoreTestUserStore(t *testing.T, setup func(t *testing.T) (store.Store, func())) {
|
||||||
|
t.Run("SetGetSystemSettings", func(t *testing.T) {
|
||||||
|
store, tearDown := setup(t)
|
||||||
|
defer tearDown()
|
||||||
|
testGetWorkspaceUsers(t, store)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGetWorkspaceUsers(t *testing.T, store store.Store) {
|
||||||
|
t.Run("GetWorkspaceUSers", func(t *testing.T) {
|
||||||
|
users, err := store.GetUsersByWorkspace("workspace_1")
|
||||||
|
require.Equal(t, 0, len(users))
|
||||||
|
require.Equal(t, sql.ErrNoRows, err)
|
||||||
|
|
||||||
|
userID := uuid.New().String()
|
||||||
|
|
||||||
|
err = store.CreateUser(&model.User{
|
||||||
|
ID: userID,
|
||||||
|
Username: "darth.vader",
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
defer store.UpdateUser(&model.User{
|
||||||
|
ID: userID,
|
||||||
|
DeleteAt: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
|
||||||
|
users, err = store.GetUsersByWorkspace("workspace_1")
|
||||||
|
require.Equal(t, 1, len(users))
|
||||||
|
require.Equal(t, "darth.vader", users[0].Username)
|
||||||
|
require.Nil(t, err)
|
||||||
|
})
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
5.0.1
|
5.1.1
|
File diff suppressed because one or more lines are too long
@ -266,6 +266,10 @@ definitions:
|
|||||||
description: Token required to register new users
|
description: Token required to register new users
|
||||||
type: string
|
type: string
|
||||||
x-go-name: SignupToken
|
x-go-name: SignupToken
|
||||||
|
title:
|
||||||
|
description: Title of the workspace
|
||||||
|
type: string
|
||||||
|
x-go-name: Title
|
||||||
updateAt:
|
updateAt:
|
||||||
description: Updated time
|
description: Updated time
|
||||||
format: int64
|
format: int64
|
||||||
@ -724,6 +728,31 @@ paths:
|
|||||||
$ref: '#/definitions/ErrorResponse'
|
$ref: '#/definitions/ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
|
/api/v1/workspaces/{workspaceID}/users:
|
||||||
|
get:
|
||||||
|
description: Returns workspace users
|
||||||
|
operationId: getWorkspaceUsers
|
||||||
|
parameters:
|
||||||
|
- description: Workspace ID
|
||||||
|
in: path
|
||||||
|
name: workspaceID
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: success
|
||||||
|
schema:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/User'
|
||||||
|
type: array
|
||||||
|
default:
|
||||||
|
description: internal error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
/workspaces/{workspaceID}/{rootID}/{fileID}:
|
/workspaces/{workspaceID}/{rootID}/{fileID}:
|
||||||
get:
|
get:
|
||||||
description: Returns the contents of an uploaded file
|
description: Returns the contents of an uploaded file
|
||||||
@ -764,7 +793,8 @@ schemes:
|
|||||||
- https
|
- https
|
||||||
securityDefinitions:
|
securityDefinitions:
|
||||||
BearerAuth:
|
BearerAuth:
|
||||||
description: 'Pass session token using Bearer authentication, e.g. set header "Authorization: Bearer <session token>"'
|
description: 'Pass session token using Bearer authentication, e.g. set header
|
||||||
|
"Authorization: Bearer <session token>"'
|
||||||
in: header
|
in: header
|
||||||
name: Authorization
|
name: Authorization
|
||||||
type: apiKey
|
type: apiKey
|
||||||
|
88
webapp/package-lock.json
generated
88
webapp/package-lock.json
generated
@ -36,6 +36,7 @@
|
|||||||
"@formatjs/ts-transformer": "^3.2.1",
|
"@formatjs/ts-transformer": "^3.2.1",
|
||||||
"@testing-library/jest-dom": "^5.11.10",
|
"@testing-library/jest-dom": "^5.11.10",
|
||||||
"@testing-library/react": "^11.2.5",
|
"@testing-library/react": "^11.2.5",
|
||||||
|
"@testing-library/user-event": "^13.1.9",
|
||||||
"@types/emoji-mart": "^3.0.4",
|
"@types/emoji-mart": "^3.0.4",
|
||||||
"@types/jest": "^26.0.21",
|
"@types/jest": "^26.0.21",
|
||||||
"@types/marked": "^2.0.0",
|
"@types/marked": "^2.0.0",
|
||||||
@ -653,9 +654,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.11.2",
|
"version": "7.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||||
"integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
|
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
}
|
}
|
||||||
@ -1540,15 +1541,6 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@testing-library/dom/node_modules/@babel/runtime": {
|
|
||||||
"version": "7.13.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
|
||||||
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@testing-library/jest-dom": {
|
"node_modules/@testing-library/jest-dom": {
|
||||||
"version": "5.11.10",
|
"version": "5.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.10.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.10.tgz",
|
||||||
@ -1596,13 +1588,20 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@testing-library/react/node_modules/@babel/runtime": {
|
"node_modules/@testing-library/user-event": {
|
||||||
"version": "7.13.10",
|
"version": "13.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.1.9.tgz",
|
||||||
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
"integrity": "sha512-NZr0zL2TMOs2qk+dNlqrAdbaRW5dAmYwd1yuQ4r7HpkVEOj0MWuUjDWwKhcLd/atdBy8ZSMHSKp+kXSQe47ezg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.13.4"
|
"@babel/runtime": "^7.12.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@testing-library/dom": ">=7.21.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/aria-query": {
|
"node_modules/@types/aria-query": {
|
||||||
@ -12879,14 +12878,6 @@
|
|||||||
"react-transition-group": "^4.3.0"
|
"react-transition-group": "^4.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-select/node_modules/@babel/runtime": {
|
|
||||||
"version": "7.13.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
|
||||||
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
|
||||||
"dependencies": {
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-simplemde-editor": {
|
"node_modules/react-simplemde-editor": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-simplemde-editor/-/react-simplemde-editor-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-simplemde-editor/-/react-simplemde-editor-4.1.3.tgz",
|
||||||
@ -16879,9 +16870,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
"version": "7.11.2",
|
"version": "7.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
|
||||||
"integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
|
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
}
|
}
|
||||||
@ -17685,17 +17676,6 @@
|
|||||||
"dom-accessibility-api": "^0.5.4",
|
"dom-accessibility-api": "^0.5.4",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"pretty-format": "^26.6.2"
|
"pretty-format": "^26.6.2"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": {
|
|
||||||
"version": "7.13.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
|
||||||
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@testing-library/jest-dom": {
|
"@testing-library/jest-dom": {
|
||||||
@ -17734,17 +17714,15 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@testing-library/dom": "^7.28.1"
|
"@testing-library/dom": "^7.28.1"
|
||||||
},
|
}
|
||||||
"dependencies": {
|
},
|
||||||
"@babel/runtime": {
|
"@testing-library/user-event": {
|
||||||
"version": "7.13.10",
|
"version": "13.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.1.9.tgz",
|
||||||
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
"integrity": "sha512-NZr0zL2TMOs2qk+dNlqrAdbaRW5dAmYwd1yuQ4r7HpkVEOj0MWuUjDWwKhcLd/atdBy8ZSMHSKp+kXSQe47ezg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.13.4"
|
"@babel/runtime": "^7.12.5"
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/aria-query": {
|
"@types/aria-query": {
|
||||||
@ -27014,16 +26992,6 @@
|
|||||||
"prop-types": "^15.6.0",
|
"prop-types": "^15.6.0",
|
||||||
"react-input-autosize": "^3.0.0",
|
"react-input-autosize": "^3.0.0",
|
||||||
"react-transition-group": "^4.3.0"
|
"react-transition-group": "^4.3.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": {
|
|
||||||
"version": "7.13.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
|
||||||
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
|
||||||
"requires": {
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-simplemde-editor": {
|
"react-simplemde-editor": {
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
"cypress:run:firefox": "cypress run --browser firefox",
|
"cypress:run:firefox": "cypress run --browser firefox",
|
||||||
"cypress:run:edge": "cypress run --browser edge",
|
"cypress:run:edge": "cypress run --browser edge",
|
||||||
"cypress:run:electron": "cypress run --browser electron",
|
"cypress:run:electron": "cypress run --browser electron",
|
||||||
"cypress:open": "cypress open"
|
"cypress:open": "cypress open",
|
||||||
|
"updatesnapshots": "jest --updateSnapshot"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cypress": "^6.8.0",
|
"cypress": "^6.8.0",
|
||||||
@ -70,6 +71,7 @@
|
|||||||
"@formatjs/ts-transformer": "^3.2.1",
|
"@formatjs/ts-transformer": "^3.2.1",
|
||||||
"@testing-library/jest-dom": "^5.11.10",
|
"@testing-library/jest-dom": "^5.11.10",
|
||||||
"@testing-library/react": "^11.2.5",
|
"@testing-library/react": "^11.2.5",
|
||||||
|
"@testing-library/user-event": "^13.1.9",
|
||||||
"@types/emoji-mart": "^3.0.4",
|
"@types/emoji-mart": "^3.0.4",
|
||||||
"@types/jest": "^26.0.21",
|
"@types/jest": "^26.0.21",
|
||||||
"@types/marked": "^2.0.0",
|
"@types/marked": "^2.0.0",
|
||||||
|
@ -27,7 +27,6 @@ const Comment: FC<Props> = (props: Props) => {
|
|||||||
const html = Utils.htmlFromMarkdown(comment.title)
|
const html = Utils.htmlFromMarkdown(comment.title)
|
||||||
|
|
||||||
const [username, setUsername] = useState('')
|
const [username, setUsername] = useState('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
UserCache.shared.getUser(userId).then((user) => {
|
UserCache.shared.getUser(userId).then((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
|
@ -0,0 +1,185 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`components/properties/user not readonly 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="UserProperty css-2b097c-container"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-atomic="false"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-relevant="additions text"
|
||||||
|
class="css-1f43avz-a11yText-A11yText"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class=" css-pwgt1w-Control"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=" css-kpfmlq-ValueContainer"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=" css-1wa3eu0-placeholder"
|
||||||
|
>
|
||||||
|
Select...
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="css-1shkodo-Input"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
style="display: inline-block;"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
autocapitalize="none"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
id="react-select-2-input"
|
||||||
|
spellcheck="false"
|
||||||
|
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
|
||||||
|
tabindex="0"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class=" css-1hb7zxy-IndicatorsContainer"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class=" css-43ykx9-indicatorSeparator"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
class=" css-19sxey8-indicatorContainer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="css-tj5bde-Svg"
|
||||||
|
focusable="false"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`components/properties/user readonly view 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="UserProperty octo-propertyvalue"
|
||||||
|
>
|
||||||
|
user-id-1
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`components/properties/user user dropdown open 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="UserProperty css-2b097c-container"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-atomic="false"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-relevant="additions text"
|
||||||
|
class="css-1f43avz-a11yText-A11yText"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
id="aria-selection"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
id="aria-context"
|
||||||
|
>
|
||||||
|
Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class=" css-pwgt1w-Control"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=" css-kpfmlq-ValueContainer"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=" css-1wa3eu0-placeholder"
|
||||||
|
>
|
||||||
|
Select...
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="css-1shkodo-Input"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
style="display: inline-block;"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-autocomplete="list"
|
||||||
|
autocapitalize="none"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
id="react-select-3-input"
|
||||||
|
spellcheck="false"
|
||||||
|
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
|
||||||
|
tabindex="0"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class=" css-1hb7zxy-IndicatorsContainer"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class=" css-43ykx9-indicatorSeparator"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
class=" css-hl9mox-indicatorContainer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="css-tj5bde-Svg"
|
||||||
|
focusable="false"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class=" css-7p3rb2-menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=" css-1m3ubgr-MenuList"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=" css-gg45go-NoOptionsMessage"
|
||||||
|
>
|
||||||
|
No options
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
4
webapp/src/components/properties/user/user.scss
Normal file
4
webapp/src/components/properties/user/user.scss
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.UserProperty {
|
||||||
|
margin-right: 20px;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
116
webapp/src/components/properties/user/user.test.tsx
Normal file
116
webapp/src/components/properties/user/user.test.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import {IntlProvider} from 'react-intl'
|
||||||
|
import {render, wait} from '@testing-library/react'
|
||||||
|
|
||||||
|
import {act} from 'react-dom/test-utils'
|
||||||
|
|
||||||
|
import userEvent from '@testing-library/user-event'
|
||||||
|
|
||||||
|
import UserProperty from './user'
|
||||||
|
|
||||||
|
const wrapIntl = (children: any) => <IntlProvider locale='en'>{children}</IntlProvider>
|
||||||
|
|
||||||
|
const fetchMock = require('fetch-mock-jest')
|
||||||
|
|
||||||
|
describe('components/properties/user', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
fetchMock.get('http://localhost/api/v1/workspaces/0/users', JSON.stringify([
|
||||||
|
{
|
||||||
|
id: 'user-id-1',
|
||||||
|
username: 'username-1',
|
||||||
|
email: 'user-1@example.com',
|
||||||
|
props: {},
|
||||||
|
create_at: 1621315184,
|
||||||
|
update_at: 1621315184,
|
||||||
|
delete_at: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'user-id-2',
|
||||||
|
username: 'username-2',
|
||||||
|
email: 'user-2@example.com',
|
||||||
|
props: {},
|
||||||
|
create_at: 1621315184,
|
||||||
|
update_at: 1621315184,
|
||||||
|
delete_at: 0,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
fetchMock.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('not readonly', async () => {
|
||||||
|
const component = wrapIntl(
|
||||||
|
<UserProperty
|
||||||
|
value={'user-id-1'}
|
||||||
|
readonly={false}
|
||||||
|
onChange={() => {
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
let container
|
||||||
|
act(() => {
|
||||||
|
const renderResult = render(component)
|
||||||
|
container = renderResult.container
|
||||||
|
})
|
||||||
|
await wait()
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('readonly view', async () => {
|
||||||
|
const component = wrapIntl(
|
||||||
|
<UserProperty
|
||||||
|
value={'user-id-1'}
|
||||||
|
readonly={true}
|
||||||
|
onChange={() => {
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
let container
|
||||||
|
act(() => {
|
||||||
|
const renderResult = render(component)
|
||||||
|
container = renderResult.container
|
||||||
|
})
|
||||||
|
await wait()
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('user dropdown open', async () => {
|
||||||
|
const component = wrapIntl(
|
||||||
|
<UserProperty
|
||||||
|
value={'user-id-1'}
|
||||||
|
readonly={false}
|
||||||
|
onChange={() => {
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
let container: Element | DocumentFragment = {} as Element
|
||||||
|
act(() => {
|
||||||
|
const renderResult = render(component)
|
||||||
|
container = renderResult.container
|
||||||
|
})
|
||||||
|
await wait()
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
// this is the actual element where the click event triggers
|
||||||
|
// opening of the dropdown
|
||||||
|
const userProperty = container.querySelector('.UserProperty > div > div:nth-child(1) > div:nth-child(2) > div > input')
|
||||||
|
expect(userProperty).not.toBeNull()
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
userEvent.click(userProperty as Element)
|
||||||
|
})
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
} else {
|
||||||
|
throw new Error('container should have been initialized')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
47
webapp/src/components/properties/user/user.tsx
Normal file
47
webapp/src/components/properties/user/user.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React, {useContext} from 'react'
|
||||||
|
import Select from 'react-select'
|
||||||
|
|
||||||
|
import {IUser, WorkspaceUsersContext, WorkspaceUsersContextData} from '../../../user'
|
||||||
|
|
||||||
|
import './user.scss'
|
||||||
|
import {getSelectBaseStyle} from '../../../theme'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: string,
|
||||||
|
readonly: boolean,
|
||||||
|
onChange: (value: string) => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
const UserProperty = (props: Props): JSX.Element => {
|
||||||
|
const workspaceUsers = useContext<WorkspaceUsersContextData>(WorkspaceUsersContext)
|
||||||
|
|
||||||
|
if (props.readonly) {
|
||||||
|
return (<div className='UserProperty octo-propertyvalue'>{workspaceUsers.usersById.get(props.value)?.username || props.value}</div>)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
options={workspaceUsers.users}
|
||||||
|
isSearchable={true}
|
||||||
|
isClearable={true}
|
||||||
|
backspaceRemovesValue={true}
|
||||||
|
className={'UserProperty'}
|
||||||
|
styles={getSelectBaseStyle()}
|
||||||
|
getOptionLabel={(o: IUser) => o.username}
|
||||||
|
getOptionValue={(a: IUser) => a.id}
|
||||||
|
value={workspaceUsers.usersById.get(props.value) || null}
|
||||||
|
onChange={(item, action) => {
|
||||||
|
if (action.action === 'select-option') {
|
||||||
|
props.onChange(item?.id || '')
|
||||||
|
} else if (action.action === 'clear') {
|
||||||
|
props.onChange('')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserProperty
|
@ -18,6 +18,7 @@ import Label from '../widgets/label'
|
|||||||
import EditableDayPicker from '../widgets/editableDayPicker'
|
import EditableDayPicker from '../widgets/editableDayPicker'
|
||||||
import Switch from '../widgets/switch'
|
import Switch from '../widgets/switch'
|
||||||
|
|
||||||
|
import UserProperty from './properties/user/user'
|
||||||
import MultiSelectProperty from './properties/multiSelect'
|
import MultiSelectProperty from './properties/multiSelect'
|
||||||
import URLProperty from './properties/link/link'
|
import URLProperty from './properties/link/link'
|
||||||
|
|
||||||
@ -133,19 +134,15 @@ const PropertyValueElement = (props:Props): JSX.Element => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else if (propertyTemplate.type === 'url') {
|
} else if (propertyTemplate.type === 'person') {
|
||||||
return (
|
return (
|
||||||
<URLProperty
|
<UserProperty
|
||||||
value={value as string}
|
value={propertyValue as string}
|
||||||
onChange={setValue}
|
readonly={readOnly}
|
||||||
onSave={() => mutator.changePropertyValue(card, propertyTemplate.id, value)}
|
onChange={(newValue) => mutator.changePropertyValue(card, propertyTemplate.id, newValue)}
|
||||||
onCancel={() => setValue(propertyValue)}
|
|
||||||
validator={(newValue) => validateProp(propertyTemplate.type, newValue)}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
} else if (propertyTemplate.type === 'date') {
|
||||||
|
|
||||||
if (propertyTemplate.type === 'date') {
|
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
return <div className='octo-propertyvalue'>{displayValue}</div>
|
return <div className='octo-propertyvalue'>{displayValue}</div>
|
||||||
}
|
}
|
||||||
@ -156,6 +153,16 @@ const PropertyValueElement = (props:Props): JSX.Element => {
|
|||||||
onChange={(newValue) => mutator.changePropertyValue(card, propertyTemplate.id, newValue)}
|
onChange={(newValue) => mutator.changePropertyValue(card, propertyTemplate.id, newValue)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
} else if (propertyTemplate.type === 'url') {
|
||||||
|
return (
|
||||||
|
<URLProperty
|
||||||
|
value={value as string}
|
||||||
|
onChange={setValue}
|
||||||
|
onSave={() => mutator.changePropertyValue(card, propertyTemplate.id, value)}
|
||||||
|
onCancel={() => setValue(propertyValue)}
|
||||||
|
validator={(newValue) => validateProp(propertyTemplate.type, newValue)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propertyTemplate.type === 'checkbox') {
|
if (propertyTemplate.type === 'checkbox') {
|
||||||
|
@ -359,6 +359,15 @@ class OctoClient {
|
|||||||
const blob = await response.blob()
|
const blob = await response.blob()
|
||||||
return URL.createObjectURL(blob)
|
return URL.createObjectURL(blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getWorkspaceUsers(): Promise<Array<IUser>> {
|
||||||
|
const path = this.workspacePath() + '/users'
|
||||||
|
const response = await fetch(this.serverUrl + path, {headers: this.headers()})
|
||||||
|
if (response.status !== 200) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return (await this.getJson(response, [])) as IUser[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const octoClient = new OctoClient()
|
const octoClient = new OctoClient()
|
||||||
|
@ -16,6 +16,7 @@ import {Utils} from '../utils'
|
|||||||
import {BoardTree, MutableBoardTree} from '../viewModel/boardTree'
|
import {BoardTree, MutableBoardTree} from '../viewModel/boardTree'
|
||||||
import {MutableWorkspaceTree, WorkspaceTree} from '../viewModel/workspaceTree'
|
import {MutableWorkspaceTree, WorkspaceTree} from '../viewModel/workspaceTree'
|
||||||
import './boardPage.scss'
|
import './boardPage.scss'
|
||||||
|
import {IUser, WorkspaceUsersContext, WorkspaceUsersContextData} from '../user'
|
||||||
|
|
||||||
type Props = RouteComponentProps<{workspaceId?: string}> & {
|
type Props = RouteComponentProps<{workspaceId?: string}> & {
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
@ -29,6 +30,7 @@ type State = {
|
|||||||
workspaceTree: WorkspaceTree
|
workspaceTree: WorkspaceTree
|
||||||
boardTree?: BoardTree
|
boardTree?: BoardTree
|
||||||
syncFailed?: boolean
|
syncFailed?: boolean
|
||||||
|
workspaceUsers: WorkspaceUsersContextData
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardPage extends React.Component<Props, State> {
|
class BoardPage extends React.Component<Props, State> {
|
||||||
@ -57,8 +59,13 @@ class BoardPage extends React.Component<Props, State> {
|
|||||||
boardId,
|
boardId,
|
||||||
viewId,
|
viewId,
|
||||||
workspaceTree: new MutableWorkspaceTree(),
|
workspaceTree: new MutableWorkspaceTree(),
|
||||||
|
workspaceUsers: {
|
||||||
|
users: new Array<IUser>(),
|
||||||
|
usersById: new Map<string, IUser>(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setWorkspaceUsers()
|
||||||
Utils.log(`BoardPage. boardId: ${boardId}`)
|
Utils.log(`BoardPage. boardId: ${boardId}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +95,28 @@ class BoardPage extends React.Component<Props, State> {
|
|||||||
document.title = 'OCTO'
|
document.title = 'OCTO'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.state.workspace?.id !== prevState.workspace?.id) {
|
||||||
|
this.setWorkspaceUsers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setWorkspaceUsers() {
|
||||||
|
const workspaceUsers = await octoClient.getWorkspaceUsers()
|
||||||
|
|
||||||
|
// storing workspaceUsersById in state to avoid re-computation in each render cycle
|
||||||
|
this.setState({
|
||||||
|
workspaceUsers: {
|
||||||
|
users: workspaceUsers,
|
||||||
|
usersById: this.getIdToWorkspaceUsers(workspaceUsers),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getIdToWorkspaceUsers(users: Array<IUser>): Map<string, IUser> {
|
||||||
|
return users.reduce((acc: Map<string, IUser>, user: IUser) => {
|
||||||
|
acc.set(user.id, user)
|
||||||
|
return acc
|
||||||
|
}, new Map())
|
||||||
}
|
}
|
||||||
|
|
||||||
private undoRedoHandler = async (keyName: string, e: KeyboardEvent) => {
|
private undoRedoHandler = async (keyName: string, e: KeyboardEvent) => {
|
||||||
@ -158,27 +187,29 @@ class BoardPage extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='BoardPage'>
|
<WorkspaceUsersContext.Provider value={this.state.workspaceUsers}>
|
||||||
<HotKeys
|
<div className='BoardPage'>
|
||||||
keyName='shift+ctrl+z,shift+cmd+z,ctrl+z,cmd+z'
|
<HotKeys
|
||||||
onKeyDown={this.undoRedoHandler}
|
keyName='shift+ctrl+z,shift+cmd+z,ctrl+z,cmd+z'
|
||||||
/>
|
onKeyDown={this.undoRedoHandler}
|
||||||
<Workspace
|
/>
|
||||||
workspace={workspace}
|
<Workspace
|
||||||
workspaceTree={workspaceTree}
|
workspace={workspace}
|
||||||
boardTree={this.state.boardTree}
|
workspaceTree={workspaceTree}
|
||||||
showView={(id, boardId) => {
|
boardTree={this.state.boardTree}
|
||||||
this.showView(id, boardId)
|
showView={(id, boardId) => {
|
||||||
}}
|
this.showView(id, boardId)
|
||||||
showBoard={(id) => {
|
}}
|
||||||
this.showBoard(id)
|
showBoard={(id) => {
|
||||||
}}
|
this.showBoard(id)
|
||||||
setSearchText={(text) => {
|
}}
|
||||||
this.setSearchText(text)
|
setSearchText={(text) => {
|
||||||
}}
|
this.setSearchText(text)
|
||||||
readonly={this.props.readonly || false}
|
}}
|
||||||
/>
|
readonly={this.props.readonly || false}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</WorkspaceUsersContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {CSSObject} from '@emotion/serialize'
|
||||||
|
|
||||||
export type Theme = {
|
export type Theme = {
|
||||||
mainBg: string,
|
mainBg: string,
|
||||||
mainFg: string,
|
mainFg: string,
|
||||||
@ -156,3 +158,67 @@ export function initThemes(): void {
|
|||||||
}
|
}
|
||||||
loadTheme()
|
loadTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSelectBaseStyle() {
|
||||||
|
return {
|
||||||
|
dropdownIndicator: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
display: 'none !important',
|
||||||
|
}),
|
||||||
|
indicatorSeparator: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
display: 'none',
|
||||||
|
}),
|
||||||
|
loadingIndicator: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
display: 'none',
|
||||||
|
}),
|
||||||
|
clearIndicator: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
display: 'none',
|
||||||
|
}),
|
||||||
|
menu: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
width: 'unset',
|
||||||
|
background: 'rgb(var(--main-bg))',
|
||||||
|
}),
|
||||||
|
option: (provided: CSSObject, state: { isFocused: boolean }): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
background: state.isFocused ? 'rgba(var(--main-fg), 0.1)' : 'rgb(var(--main-bg))',
|
||||||
|
color: state.isFocused ? 'rgb(var(--main-fg))' : 'rgb(var(--main-fg))',
|
||||||
|
padding: '2px 8px',
|
||||||
|
}),
|
||||||
|
control: (): CSSObject => ({
|
||||||
|
border: 0,
|
||||||
|
width: '100%',
|
||||||
|
margin: '4px 0 0 0',
|
||||||
|
|
||||||
|
// display: 'flex',
|
||||||
|
// marginTop: 0,
|
||||||
|
}),
|
||||||
|
valueContainer: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
padding: '0 5px',
|
||||||
|
overflow: 'unset',
|
||||||
|
|
||||||
|
// height: '20px',
|
||||||
|
}),
|
||||||
|
singleValue: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
color: 'rgb(var(--main-fg))',
|
||||||
|
overflow: 'unset',
|
||||||
|
maxWidth: 'calc(100% - 20px)',
|
||||||
|
}),
|
||||||
|
input: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
paddingBottom: 0,
|
||||||
|
paddingTop: 0,
|
||||||
|
marginBottom: 0,
|
||||||
|
marginTop: 0,
|
||||||
|
}),
|
||||||
|
menuList: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
overflowY: 'unset',
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,6 +5,11 @@ import React from 'react'
|
|||||||
|
|
||||||
const UserContext = React.createContext(undefined as IUser|undefined)
|
const UserContext = React.createContext(undefined as IUser|undefined)
|
||||||
|
|
||||||
|
const WorkspaceUsersContext = React.createContext({
|
||||||
|
users: new Array<IUser>(),
|
||||||
|
usersById: new Map<string, IUser>(),
|
||||||
|
})
|
||||||
|
|
||||||
interface IUser {
|
interface IUser {
|
||||||
id: string,
|
id: string,
|
||||||
username: string,
|
username: string,
|
||||||
@ -14,4 +19,9 @@ interface IUser {
|
|||||||
updateAt: number,
|
updateAt: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export {IUser, UserContext}
|
type WorkspaceUsersContextData = {
|
||||||
|
users: Array<IUser>
|
||||||
|
usersById: Map<string, IUser>
|
||||||
|
}
|
||||||
|
|
||||||
|
export {IUser, UserContext, WorkspaceUsersContext, WorkspaceUsersContextData}
|
||||||
|
@ -187,6 +187,21 @@ exports[`widgets/PropertyMenu should match snapshot 1`] = `
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="MenuOption TextOption menu-option"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="noicon"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="menu-name"
|
||||||
|
>
|
||||||
|
Person
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="noicon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
>
|
>
|
||||||
|
@ -129,6 +129,11 @@ const PropertyMenu = React.memo((props: Props) => {
|
|||||||
name={typeDisplayName(intl, 'date')}
|
name={typeDisplayName(intl, 'date')}
|
||||||
onClick={() => props.onTypeChanged('date')}
|
onClick={() => props.onTypeChanged('date')}
|
||||||
/>
|
/>
|
||||||
|
<Menu.Text
|
||||||
|
id='person'
|
||||||
|
name={typeDisplayName(intl, 'person')}
|
||||||
|
onClick={() => props.onTypeChanged('person')}
|
||||||
|
/>
|
||||||
<Menu.Text
|
<Menu.Text
|
||||||
id='checkbox'
|
id='checkbox'
|
||||||
name={typeDisplayName(intl, 'checkbox')}
|
name={typeDisplayName(intl, 'checkbox')}
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {useIntl} from 'react-intl'
|
import {useIntl} from 'react-intl'
|
||||||
import {ActionMeta, ValueType, FormatOptionLabelMeta} from 'react-select'
|
import {ActionMeta, FormatOptionLabelMeta, ValueType} from 'react-select'
|
||||||
import CreatableSelect from 'react-select/creatable'
|
import CreatableSelect from 'react-select/creatable'
|
||||||
|
|
||||||
import {CSSObject} from '@emotion/serialize'
|
import {CSSObject} from '@emotion/serialize'
|
||||||
|
|
||||||
import {IPropertyOption} from '../blocks/board'
|
import {IPropertyOption} from '../blocks/board'
|
||||||
import {Constants} from '../constants'
|
import {Constants} from '../constants'
|
||||||
|
|
||||||
|
import {getSelectBaseStyle} from '../theme'
|
||||||
|
|
||||||
import Menu from './menu'
|
import Menu from './menu'
|
||||||
import MenuWrapper from './menuWrapper'
|
import MenuWrapper from './menuWrapper'
|
||||||
import IconButton from './buttons/iconButton'
|
import IconButton from './buttons/iconButton'
|
||||||
@ -90,70 +93,47 @@ const ValueSelectorLabel = React.memo((props: LabelProps): JSX.Element => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const valueSelectorStyle = {
|
||||||
|
...getSelectBaseStyle(),
|
||||||
|
option: (provided: CSSObject, state: {isFocused: boolean}): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
background: state.isFocused ? 'rgba(var(--main-fg), 0.1)' : 'rgb(var(--main-bg))',
|
||||||
|
color: state.isFocused ? 'rgb(var(--main-fg))' : 'rgb(var(--main-fg))',
|
||||||
|
padding: '8px',
|
||||||
|
}),
|
||||||
|
control: (): CSSObject => ({
|
||||||
|
border: 0,
|
||||||
|
width: '100%',
|
||||||
|
margin: '0',
|
||||||
|
}),
|
||||||
|
valueContainer: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
padding: '0 8px',
|
||||||
|
overflow: 'unset',
|
||||||
|
}),
|
||||||
|
multiValue: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
}),
|
||||||
|
multiValueLabel: (provided: CSSObject): CSSObject => ({
|
||||||
|
...provided,
|
||||||
|
display: 'flex',
|
||||||
|
paddingLeft: 0,
|
||||||
|
padding: 0,
|
||||||
|
}),
|
||||||
|
multiValueRemove: (): CSSObject => ({
|
||||||
|
display: 'none',
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
function ValueSelector(props: Props): JSX.Element {
|
function ValueSelector(props: Props): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CreatableSelect
|
<CreatableSelect
|
||||||
isMulti={props.isMulti}
|
isMulti={props.isMulti}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
styles={{
|
styles={valueSelectorStyle}
|
||||||
indicatorsContainer: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
display: 'none',
|
|
||||||
}),
|
|
||||||
menu: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
width: 'unset',
|
|
||||||
background: 'rgb(var(--main-bg))',
|
|
||||||
}),
|
|
||||||
option: (provided: CSSObject, state: {isFocused: boolean}): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
background: state.isFocused ? 'rgba(var(--main-fg), 0.1)' : 'rgb(var(--main-bg))',
|
|
||||||
color: state.isFocused ? 'rgb(var(--main-fg))' : 'rgb(var(--main-fg))',
|
|
||||||
padding: '8px',
|
|
||||||
}),
|
|
||||||
control: (): CSSObject => ({
|
|
||||||
border: 0,
|
|
||||||
width: '100%',
|
|
||||||
margin: '0',
|
|
||||||
}),
|
|
||||||
valueContainer: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
padding: '0 8px',
|
|
||||||
overflow: 'unset',
|
|
||||||
}),
|
|
||||||
singleValue: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
color: 'rgb(var(--main-fg))',
|
|
||||||
overflow: 'unset',
|
|
||||||
maxWidth: 'calc(100% - 20px)',
|
|
||||||
}),
|
|
||||||
input: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
paddingBottom: 0,
|
|
||||||
paddingTop: 0,
|
|
||||||
marginBottom: 0,
|
|
||||||
marginTop: 0,
|
|
||||||
}),
|
|
||||||
menuList: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
overflowY: 'unset',
|
|
||||||
}),
|
|
||||||
multiValue: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
}),
|
|
||||||
multiValueLabel: (provided: CSSObject): CSSObject => ({
|
|
||||||
...provided,
|
|
||||||
display: 'flex',
|
|
||||||
paddingLeft: 0,
|
|
||||||
padding: 0,
|
|
||||||
}),
|
|
||||||
multiValueRemove: (): CSSObject => ({
|
|
||||||
display: 'none',
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
formatOptionLabel={(option: IPropertyOption, meta: FormatOptionLabelMeta<IPropertyOption, true | false>) => (
|
formatOptionLabel={(option: IPropertyOption, meta: FormatOptionLabelMeta<IPropertyOption, true | false>) => (
|
||||||
<ValueSelectorLabel
|
<ValueSelectorLabel
|
||||||
option={option}
|
option={option}
|
||||||
|
Loading…
Reference in New Issue
Block a user