mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-21 13:38:56 +02:00
Merge branch 'main' into deduplicate_category_boards
This commit is contained in:
commit
761eaa759b
@ -6,7 +6,7 @@
|
|||||||
"support_url": "https://github.com/mattermost/focalboard/issues",
|
"support_url": "https://github.com/mattermost/focalboard/issues",
|
||||||
"release_notes_url": "https://github.com/mattermost/focalboard/releases",
|
"release_notes_url": "https://github.com/mattermost/focalboard/releases",
|
||||||
"icon_path": "assets/starter-template-icon.svg",
|
"icon_path": "assets/starter-template-icon.svg",
|
||||||
"version": "7.9.0",
|
"version": "7.10.0",
|
||||||
"min_server_version": "7.2.0",
|
"min_server_version": "7.2.0",
|
||||||
"server": {
|
"server": {
|
||||||
"executables": {
|
"executables": {
|
||||||
|
2
mattermost-plugin/server/manifest.go
generated
2
mattermost-plugin/server/manifest.go
generated
@ -20,7 +20,7 @@ const manifestStr = `
|
|||||||
"support_url": "https://github.com/mattermost/focalboard/issues",
|
"support_url": "https://github.com/mattermost/focalboard/issues",
|
||||||
"release_notes_url": "https://github.com/mattermost/focalboard/releases",
|
"release_notes_url": "https://github.com/mattermost/focalboard/releases",
|
||||||
"icon_path": "assets/starter-template-icon.svg",
|
"icon_path": "assets/starter-template-icon.svg",
|
||||||
"version": "7.9.0",
|
"version": "7.10.0",
|
||||||
"min_server_version": "7.2.0",
|
"min_server_version": "7.2.0",
|
||||||
"server": {
|
"server": {
|
||||||
"executables": {
|
"executables": {
|
||||||
|
@ -17,8 +17,10 @@ import CompassIcon from '../../../../webapp/src/widgets/icons/compassIcon'
|
|||||||
|
|
||||||
import {Permission} from '../../../../webapp/src/constants'
|
import {Permission} from '../../../../webapp/src/constants'
|
||||||
|
|
||||||
import './rhsChannelBoardItem.scss'
|
|
||||||
import BoardPermissionGate from '../../../../webapp/src/components/permissions/boardPermissionGate'
|
import BoardPermissionGate from '../../../../webapp/src/components/permissions/boardPermissionGate'
|
||||||
|
import TelemetryClient, {TelemetryActions, TelemetryCategory} from '../../../../webapp/src/telemetry/telemetryClient'
|
||||||
|
|
||||||
|
import './rhsChannelBoardItem.scss'
|
||||||
|
|
||||||
const windowAny = (window as SuiteWindow)
|
const windowAny = (window as SuiteWindow)
|
||||||
|
|
||||||
@ -36,6 +38,10 @@ const RHSChannelBoardItem = (props: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleBoardClicked = (boardID: string) => {
|
const handleBoardClicked = (boardID: string) => {
|
||||||
|
// send the telemetry information for the clicked board
|
||||||
|
const extraData = {teamID: team.id, board: boardID}
|
||||||
|
TelemetryClient.trackEvent(TelemetryCategory, TelemetryActions.ClickChannelsRHSBoard, extraData)
|
||||||
|
|
||||||
window.open(`${windowAny.frontendBaseURL}/team/${team.id}/${boardID}`, '_blank', 'noopener')
|
window.open(`${windowAny.frontendBaseURL}/team/${team.id}/${boardID}`, '_blank', 'noopener')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ func jsonStringResponse(w http.ResponseWriter, code int, message string) { //nol
|
|||||||
fmt.Fprint(w, message)
|
fmt.Fprint(w, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) {
|
func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) { //nolint:unparam
|
||||||
setResponseHeader(w, "Content-Type", "application/json")
|
setResponseHeader(w, "Content-Type", "application/json")
|
||||||
w.WriteHeader(code)
|
w.WriteHeader(code)
|
||||||
_, _ = w.Write(json)
|
_, _ = w.Write(json)
|
||||||
|
@ -123,37 +123,12 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
auditRec.AddMeta("teamID", board.TeamID)
|
auditRec.AddMeta("teamID", board.TeamID)
|
||||||
auditRec.AddMeta("filename", filename)
|
auditRec.AddMeta("filename", filename)
|
||||||
|
|
||||||
fileInfo, err := a.app.GetFileInfo(filename)
|
fileInfo, fileReader, err := a.app.GetFile(board.TeamID, boardID, filename)
|
||||||
if err != nil && !model.IsErrNotFound(err) {
|
if err != nil && !model.IsErrNotFound(err) {
|
||||||
a.errorResponse(w, r, err)
|
a.errorResponse(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileInfo != nil && fileInfo.Archived {
|
|
||||||
fileMetadata := map[string]interface{}{
|
|
||||||
"archived": true,
|
|
||||||
"name": fileInfo.Name,
|
|
||||||
"size": fileInfo.Size,
|
|
||||||
"extension": fileInfo.Extension,
|
|
||||||
}
|
|
||||||
|
|
||||||
data, jsonErr := json.Marshal(fileMetadata)
|
|
||||||
if jsonErr != nil {
|
|
||||||
a.logger.Error("failed to marshal archived file metadata", mlog.String("filename", filename), mlog.Err(jsonErr))
|
|
||||||
a.errorResponse(w, r, jsonErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonBytesResponse(w, http.StatusBadRequest, data)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileReader, err := a.app.GetFileReader(board.TeamID, boardID, filename)
|
|
||||||
if err != nil && !errors.Is(err, app.ErrFileNotFound) {
|
|
||||||
a.errorResponse(w, r, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.Is(err, app.ErrFileNotFound) && board.ChannelID != "" {
|
if errors.Is(err, app.ErrFileNotFound) && board.ChannelID != "" {
|
||||||
// prior to moving from workspaces to teams, the filepath was constructed from
|
// prior to moving from workspaces to teams, the filepath was constructed from
|
||||||
// workspaceID, which is the channel ID in plugin mode.
|
// workspaceID, which is the channel ID in plugin mode.
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mattermost/focalboard/server/model"
|
||||||
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
||||||
|
|
||||||
"github.com/mattermost/focalboard/server/utils"
|
"github.com/mattermost/focalboard/server/utils"
|
||||||
@ -28,7 +29,7 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin
|
|||||||
|
|
||||||
createdFilename := utils.NewID(utils.IDTypeNone)
|
createdFilename := utils.NewID(utils.IDTypeNone)
|
||||||
fullFilename := fmt.Sprintf(`%s%s`, createdFilename, fileExtension)
|
fullFilename := fmt.Sprintf(`%s%s`, createdFilename, fileExtension)
|
||||||
filePath := filepath.Join(teamID, rootID, fullFilename)
|
filePath := filepath.Join(utils.GetBaseFilePath(), fullFilename)
|
||||||
|
|
||||||
fileSize, appErr := a.filesBackend.WriteFile(reader, filePath)
|
fileSize, appErr := a.filesBackend.WriteFile(reader, filePath)
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
@ -45,7 +46,7 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin
|
|||||||
CreateAt: now,
|
CreateAt: now,
|
||||||
UpdateAt: now,
|
UpdateAt: now,
|
||||||
DeleteAt: 0,
|
DeleteAt: 0,
|
||||||
Path: emptyString,
|
Path: filePath,
|
||||||
ThumbnailPath: emptyString,
|
ThumbnailPath: emptyString,
|
||||||
PreviewPath: emptyString,
|
PreviewPath: emptyString,
|
||||||
Name: filename,
|
Name: filename,
|
||||||
@ -59,6 +60,7 @@ func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (strin
|
|||||||
Content: "",
|
Content: "",
|
||||||
RemoteId: nil,
|
RemoteId: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.store.SaveFileInfo(fileInfo)
|
err := a.store.SaveFileInfo(fileInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -77,6 +79,7 @@ func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) {
|
|||||||
// will be the fileinfo id.
|
// will be the fileinfo id.
|
||||||
parts := strings.Split(filename, ".")
|
parts := strings.Split(filename, ".")
|
||||||
fileInfoID := parts[0][1:]
|
fileInfoID := parts[0][1:]
|
||||||
|
|
||||||
fileInfo, err := a.store.GetFileInfo(fileInfoID)
|
fileInfo, err := a.store.GetFileInfo(fileInfoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -85,6 +88,40 @@ func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) {
|
|||||||
return fileInfo, nil
|
return fileInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) GetFile(teamID, rootID, fileName string) (*mmModel.FileInfo, filestore.ReadCloseSeeker, error) {
|
||||||
|
fileInfo, err := a.GetFileInfo(fileName)
|
||||||
|
if err != nil && !model.IsErrNotFound(err) {
|
||||||
|
a.logger.Error("111")
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var filePath string
|
||||||
|
|
||||||
|
if fileInfo != nil && fileInfo.Path != "" {
|
||||||
|
filePath = fileInfo.Path
|
||||||
|
} else {
|
||||||
|
filePath = filepath.Join(teamID, rootID, fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
exists, err := a.filesBackend.FileExists(filePath)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error(fmt.Sprintf("GetFile: Failed to check if file exists as path. Path: %s, error: %e", filePath, err))
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return nil, nil, ErrFileNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
reader, err := a.filesBackend.Reader(filePath)
|
||||||
|
if err != nil {
|
||||||
|
a.logger.Error(fmt.Sprintf("GetFile: Failed to get file reader of existing file at path: %s, error: %e", filePath, err))
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileInfo, reader, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) GetFileReader(teamID, rootID, filename string) (filestore.ReadCloseSeeker, error) {
|
func (a *App) GetFileReader(teamID, rootID, filename string) (filestore.ReadCloseSeeker, error) {
|
||||||
filePath := filepath.Join(teamID, rootID, filename)
|
filePath := filepath.Join(teamID, rootID, filename)
|
||||||
exists, err := a.filesBackend.FileExists(filePath)
|
exists, err := a.filesBackend.FileExists(filePath)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -195,8 +196,8 @@ func TestSaveFile(t *testing.T) {
|
|||||||
|
|
||||||
writeFileFunc := func(reader io.Reader, path string) int64 {
|
writeFileFunc := func(reader io.Reader, path string) int64 {
|
||||||
paths := strings.Split(path, string(os.PathSeparator))
|
paths := strings.Split(path, string(os.PathSeparator))
|
||||||
assert.Equal(t, "1", paths[0])
|
assert.Equal(t, "boards", paths[0])
|
||||||
assert.Equal(t, testBoardID, paths[1])
|
assert.Equal(t, time.Now().Format("20060102"), paths[1])
|
||||||
fileName = paths[2]
|
fileName = paths[2]
|
||||||
return int64(10)
|
return int64(10)
|
||||||
}
|
}
|
||||||
@ -219,8 +220,8 @@ func TestSaveFile(t *testing.T) {
|
|||||||
|
|
||||||
writeFileFunc := func(reader io.Reader, path string) int64 {
|
writeFileFunc := func(reader io.Reader, path string) int64 {
|
||||||
paths := strings.Split(path, string(os.PathSeparator))
|
paths := strings.Split(path, string(os.PathSeparator))
|
||||||
assert.Equal(t, "1", paths[0])
|
assert.Equal(t, "boards", paths[0])
|
||||||
assert.Equal(t, "test-board-id", paths[1])
|
assert.Equal(t, time.Now().Format("20060102"), paths[1])
|
||||||
assert.Equal(t, "jpg", strings.Split(paths[2], ".")[1])
|
assert.Equal(t, "jpg", strings.Split(paths[2], ".")[1])
|
||||||
return int64(10)
|
return int64(10)
|
||||||
}
|
}
|
||||||
@ -243,8 +244,8 @@ func TestSaveFile(t *testing.T) {
|
|||||||
|
|
||||||
writeFileFunc := func(reader io.Reader, path string) int64 {
|
writeFileFunc := func(reader io.Reader, path string) int64 {
|
||||||
paths := strings.Split(path, string(os.PathSeparator))
|
paths := strings.Split(path, string(os.PathSeparator))
|
||||||
assert.Equal(t, "1", paths[0])
|
assert.Equal(t, "boards", paths[0])
|
||||||
assert.Equal(t, "test-board-id", paths[1])
|
assert.Equal(t, time.Now().Format("20060102"), paths[1])
|
||||||
assert.Equal(t, "jpg", strings.Split(paths[2], ".")[1])
|
assert.Equal(t, "jpg", strings.Split(paths[2], ".")[1])
|
||||||
return int64(10)
|
return int64(10)
|
||||||
}
|
}
|
||||||
@ -304,3 +305,80 @@ func TestGetFileInfo(t *testing.T) {
|
|||||||
assert.Nil(t, fetchedFileInfo)
|
assert.Nil(t, fetchedFileInfo)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetFile(t *testing.T) {
|
||||||
|
th, _ := SetupTestHelper(t)
|
||||||
|
|
||||||
|
t.Run("when FileInfo exists", func(t *testing.T) {
|
||||||
|
th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mmModel.FileInfo{
|
||||||
|
Id: "fileInfoID",
|
||||||
|
Path: "/path/to/file/fileName.txt",
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
mockedFileBackend := &mocks.FileBackend{}
|
||||||
|
th.App.filesBackend = mockedFileBackend
|
||||||
|
mockedReadCloseSeek := &mocks.ReadCloseSeeker{}
|
||||||
|
readerFunc := func(path string) filestore.ReadCloseSeeker {
|
||||||
|
return mockedReadCloseSeek
|
||||||
|
}
|
||||||
|
|
||||||
|
readerErrorFunc := func(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
mockedFileBackend.On("Reader", "/path/to/file/fileName.txt").Return(readerFunc, readerErrorFunc)
|
||||||
|
mockedFileBackend.On("FileExists", "/path/to/file/fileName.txt").Return(true, nil)
|
||||||
|
|
||||||
|
fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, fileInfo)
|
||||||
|
assert.NotNil(t, seeker)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when FileInfo doesn't exist", func(t *testing.T) {
|
||||||
|
th.Store.EXPECT().GetFileInfo("fileInfoID").Return(nil, nil)
|
||||||
|
|
||||||
|
mockedFileBackend := &mocks.FileBackend{}
|
||||||
|
th.App.filesBackend = mockedFileBackend
|
||||||
|
mockedReadCloseSeek := &mocks.ReadCloseSeeker{}
|
||||||
|
readerFunc := func(path string) filestore.ReadCloseSeeker {
|
||||||
|
return mockedReadCloseSeek
|
||||||
|
}
|
||||||
|
|
||||||
|
readerErrorFunc := func(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mockedFileBackend.On("Reader", "teamID/boardID/7fileInfoID.txt").Return(readerFunc, readerErrorFunc)
|
||||||
|
mockedFileBackend.On("FileExists", "teamID/boardID/7fileInfoID.txt").Return(true, nil)
|
||||||
|
|
||||||
|
fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, fileInfo)
|
||||||
|
assert.NotNil(t, seeker)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when FileInfo exists but FileInfo.Path is not set", func(t *testing.T) {
|
||||||
|
th.Store.EXPECT().GetFileInfo("fileInfoID").Return(&mmModel.FileInfo{
|
||||||
|
Id: "fileInfoID",
|
||||||
|
Path: "",
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
mockedFileBackend := &mocks.FileBackend{}
|
||||||
|
th.App.filesBackend = mockedFileBackend
|
||||||
|
mockedReadCloseSeek := &mocks.ReadCloseSeeker{}
|
||||||
|
readerFunc := func(path string) filestore.ReadCloseSeeker {
|
||||||
|
return mockedReadCloseSeek
|
||||||
|
}
|
||||||
|
|
||||||
|
readerErrorFunc := func(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
mockedFileBackend.On("Reader", "teamID/boardID/7fileInfoID.txt").Return(readerFunc, readerErrorFunc)
|
||||||
|
mockedFileBackend.On("FileExists", "teamID/boardID/7fileInfoID.txt").Return(true, nil)
|
||||||
|
|
||||||
|
fileInfo, seeker, err := th.App.GetFile("teamID", "boardID", "7fileInfoID.txt")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, fileInfo)
|
||||||
|
assert.NotNil(t, seeker)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -380,6 +380,8 @@ func (c *Client) GetCards(boardID string, page int, perPage int) ([]*model.Card,
|
|||||||
return nil, BuildErrorResponse(r, err)
|
return nil, BuildErrorResponse(r, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
var cards []*model.Card
|
var cards []*model.Card
|
||||||
if err := json.NewDecoder(r.Body).Decode(&cards); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&cards); err != nil {
|
||||||
return nil, BuildErrorResponse(r, err)
|
return nil, BuildErrorResponse(r, err)
|
||||||
@ -398,6 +400,8 @@ func (c *Client) PatchCard(cardID string, cardPatch *model.CardPatch, disableNot
|
|||||||
return nil, BuildErrorResponse(r, err)
|
return nil, BuildErrorResponse(r, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
var cardNew *model.Card
|
var cardNew *model.Card
|
||||||
if err := json.NewDecoder(r.Body).Decode(&cardNew); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&cardNew); err != nil {
|
||||||
return nil, BuildErrorResponse(r, err)
|
return nil, BuildErrorResponse(r, err)
|
||||||
@ -412,6 +416,8 @@ func (c *Client) GetCard(cardID string) (*model.Card, *Response) {
|
|||||||
return nil, BuildErrorResponse(r, err)
|
return nil, BuildErrorResponse(r, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
var card *model.Card
|
var card *model.Card
|
||||||
if err := json.NewDecoder(r.Body).Decode(&card); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&card); err != nil {
|
||||||
return nil, BuildErrorResponse(r, err)
|
return nil, BuildErrorResponse(r, err)
|
||||||
@ -450,6 +456,7 @@ func (c *Client) DeleteCategory(teamID, categoryID string) *Response {
|
|||||||
return BuildErrorResponse(r, err)
|
return BuildErrorResponse(r, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer closeBody(r)
|
||||||
return BuildResponse(r)
|
return BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,6 +1056,7 @@ func (c *Client) HideBoard(teamID, categoryID, boardID string) *Response {
|
|||||||
return BuildErrorResponse(r, err)
|
return BuildErrorResponse(r, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer closeBody(r)
|
||||||
return BuildResponse(r)
|
return BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1058,5 +1066,6 @@ func (c *Client) UnhideBoard(teamID, categoryID, boardID string) *Response {
|
|||||||
return BuildErrorResponse(r, err)
|
return BuildErrorResponse(r, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer closeBody(r)
|
||||||
return BuildResponse(r)
|
return BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
// It should be maintained in chronological order with most current
|
// It should be maintained in chronological order with most current
|
||||||
// release at the front of the list.
|
// release at the front of the list.
|
||||||
var versions = []string{
|
var versions = []string{
|
||||||
|
"7.10.0",
|
||||||
"7.9.0",
|
"7.9.0",
|
||||||
"7.8.0",
|
"7.8.0",
|
||||||
"7.7.0",
|
"7.7.0",
|
||||||
|
@ -22,6 +22,7 @@ func (s *SQLStore) saveFileInfo(db sq.BaseRunner, fileInfo *mmModel.FileInfo) er
|
|||||||
"extension",
|
"extension",
|
||||||
"size",
|
"size",
|
||||||
"delete_at",
|
"delete_at",
|
||||||
|
"path",
|
||||||
"archived",
|
"archived",
|
||||||
).
|
).
|
||||||
Values(
|
Values(
|
||||||
@ -31,6 +32,7 @@ func (s *SQLStore) saveFileInfo(db sq.BaseRunner, fileInfo *mmModel.FileInfo) er
|
|||||||
fileInfo.Extension,
|
fileInfo.Extension,
|
||||||
fileInfo.Size,
|
fileInfo.Size,
|
||||||
fileInfo.DeleteAt,
|
fileInfo.DeleteAt,
|
||||||
|
fileInfo.Path,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,6 +59,7 @@ func (s *SQLStore) getFileInfo(db sq.BaseRunner, id string) (*mmModel.FileInfo,
|
|||||||
"extension",
|
"extension",
|
||||||
"size",
|
"size",
|
||||||
"archived",
|
"archived",
|
||||||
|
"path",
|
||||||
).
|
).
|
||||||
From(s.tablePrefix + "file_info").
|
From(s.tablePrefix + "file_info").
|
||||||
Where(sq.Eq{"Id": id})
|
Where(sq.Eq{"Id": id})
|
||||||
@ -73,6 +76,7 @@ func (s *SQLStore) getFileInfo(db sq.BaseRunner, id string) (*mmModel.FileInfo,
|
|||||||
&fileInfo.Extension,
|
&fileInfo.Extension,
|
||||||
&fileInfo.Size,
|
&fileInfo.Size,
|
||||||
&fileInfo.Archived,
|
&fileInfo.Archived,
|
||||||
|
&fileInfo.Path,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
SELECT 1;
|
@ -0,0 +1 @@
|
|||||||
|
{{ addColumnIfNeeded "file_info" "path" "varchar(512)" "" }}
|
@ -2,6 +2,7 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -120,3 +121,7 @@ func DedupeStringArr(arr []string) []string {
|
|||||||
|
|
||||||
return dedupedArr
|
return dedupedArr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetBaseFilePath() string {
|
||||||
|
return path.Join("boards", time.Now().Format("20060102"))
|
||||||
|
}
|
||||||
|
@ -1,14 +1,42 @@
|
|||||||
{
|
{
|
||||||
|
"AppBar.Tooltip": "Veksle lenkede tavler",
|
||||||
|
"Attachment.Attachment-title": "Vedlegg",
|
||||||
|
"AttachmentBlock.DeleteAction": "slett",
|
||||||
|
"AttachmentBlock.addElement": "legg til {type}",
|
||||||
|
"AttachmentBlock.delete": "Vedlegg slettet.",
|
||||||
|
"AttachmentBlock.failed": "Denne filen kunne ikke lastes opp fordi størrelsesgrensen er nådd.",
|
||||||
|
"AttachmentBlock.upload": "Vedlegg lastes opp.",
|
||||||
|
"AttachmentBlock.uploadSuccess": "Vedlegg lastet opp.",
|
||||||
|
"AttachmentElement.delete-confirmation-dialog-button-text": "Slett",
|
||||||
|
"AttachmentElement.download": "Last ned",
|
||||||
|
"AttachmentElement.upload-percentage": "Laster opp ...({uploadPercent}%)",
|
||||||
"BoardComponent.add-a-group": "+ Legg til gruppe",
|
"BoardComponent.add-a-group": "+ Legg til gruppe",
|
||||||
"BoardComponent.delete": "Slett",
|
"BoardComponent.delete": "Slett",
|
||||||
"BoardComponent.hidden-columns": "Skjulte kolonner",
|
"BoardComponent.hidden-columns": "Skjulte kolonner",
|
||||||
"BoardComponent.hide": "Skjul",
|
"BoardComponent.hide": "Skjul",
|
||||||
"BoardComponent.new": "+ Ny",
|
"BoardComponent.new": "+ Ny",
|
||||||
"BoardComponent.no-property": "Ingen {property}",
|
"BoardComponent.no-property": "Ingen {property}",
|
||||||
"BoardComponent.no-property-title": "Elementer med en tom {property} område kommer hit. Denne kolonnen kan ikke fjernes.",
|
"BoardComponent.no-property-title": "Elementer med tom {property} atributt legges her. Denne kolonnen kan ikke fjernes.",
|
||||||
"BoardComponent.show": "Vis",
|
"BoardComponent.show": "Vis",
|
||||||
|
"BoardMember.schemeAdmin": "Admin",
|
||||||
|
"BoardMember.schemeCommenter": "Kommentator",
|
||||||
|
"BoardMember.schemeEditor": "Redaktør",
|
||||||
|
"BoardMember.schemeNone": "Ingen",
|
||||||
|
"BoardMember.schemeViewer": "Viser",
|
||||||
|
"BoardMember.unlinkChannel": "Fjern lenke",
|
||||||
"BoardPage.newVersion": "En ny versjon av Boards er tilgjengelig, klikk her for å laste inn på nytt.",
|
"BoardPage.newVersion": "En ny versjon av Boards er tilgjengelig, klikk her for å laste inn på nytt.",
|
||||||
"BoardPage.syncFailed": "Tavle kan slettes eller adgangen trekkes tilbake.",
|
"BoardPage.syncFailed": "Tavle kan slettes eller adgangen trekkes tilbake.",
|
||||||
|
"BoardTemplateSelector.add-template": "Lag ny mal",
|
||||||
|
"BoardTemplateSelector.create-empty-board": "Opprett tom tavle",
|
||||||
|
"BoardTemplateSelector.delete-template": "Slett",
|
||||||
|
"BoardTemplateSelector.description": "Legg til en tavle til sidestolpen med hvilken mal du vil fra listen under, eller start med en helt tom tavle.",
|
||||||
|
"BoardTemplateSelector.edit-template": "Rediger",
|
||||||
|
"BoardTemplateSelector.plugin.no-content-description": "Legg til en tavle i sidestolpen med hvilken mal du vil, eller start med en tom tavle.",
|
||||||
|
"BoardTemplateSelector.plugin.no-content-title": "Lag ny tavle",
|
||||||
|
"BoardTemplateSelector.title": "Lag ny tavle",
|
||||||
|
"BoardTemplateSelector.use-this-template": "Bruk denne malen",
|
||||||
|
"BoardsSwitcher.Title": "Finn tavle",
|
||||||
|
"BoardsUnfurl.Limited": "Flere detaljer er skjult fordi kortet er arkivert",
|
||||||
"BoardsUnfurl.Remainder": "+{remainder} mer",
|
"BoardsUnfurl.Remainder": "+{remainder} mer",
|
||||||
"BoardsUnfurl.Updated": "Oppdatert {time}",
|
"BoardsUnfurl.Updated": "Oppdatert {time}",
|
||||||
"Calculations.Options.average.displayName": "Gjennomsnitt",
|
"Calculations.Options.average.displayName": "Gjennomsnitt",
|
||||||
@ -16,11 +44,142 @@
|
|||||||
"Calculations.Options.count.displayName": "Antall",
|
"Calculations.Options.count.displayName": "Antall",
|
||||||
"Calculations.Options.count.label": "Antall",
|
"Calculations.Options.count.label": "Antall",
|
||||||
"Calculations.Options.countChecked.displayName": "Avkrysset",
|
"Calculations.Options.countChecked.displayName": "Avkrysset",
|
||||||
"Calculations.Options.countChecked.label": "Antall avsjekket",
|
"Calculations.Options.countChecked.label": "Antall valgt",
|
||||||
"Calculations.Options.countUnchecked.displayName": "Ikke avmerket",
|
"Calculations.Options.countUnchecked.displayName": "Ikke avmerket",
|
||||||
"Calculations.Options.countUnchecked.label": "Antall Ikke Avmerket",
|
"Calculations.Options.countUnchecked.label": "Antall ikke valgt",
|
||||||
"Calculations.Options.countUniqueValue.displayName": "Unik",
|
"Calculations.Options.countUniqueValue.displayName": "Unik",
|
||||||
"Calculations.Options.countUniqueValue.label": "Antall Unike Verdier",
|
"Calculations.Options.countUniqueValue.label": "Antall unike verdier",
|
||||||
"Calculations.Options.countValue.displayName": "Verdier",
|
"Calculations.Options.countValue.displayName": "Verdier",
|
||||||
"Calculations.Options.countValue.label": "Antall Verdier"
|
"Calculations.Options.countValue.label": "Antall verdier",
|
||||||
|
"Calculations.Options.dateRange.displayName": "Tidsrom",
|
||||||
|
"Calculations.Options.dateRange.label": "Tidsrom",
|
||||||
|
"Calculations.Options.earliest.displayName": "Tiligst",
|
||||||
|
"Calculations.Options.earliest.label": "Tiligst",
|
||||||
|
"Calculations.Options.latest.displayName": "Senest",
|
||||||
|
"Calculations.Options.latest.label": "Senest",
|
||||||
|
"Calculations.Options.max.displayName": "Maks",
|
||||||
|
"Calculations.Options.max.label": "Maks",
|
||||||
|
"Calculations.Options.median.displayName": "Median",
|
||||||
|
"Calculations.Options.median.label": "Median",
|
||||||
|
"Calculations.Options.min.displayName": "Min",
|
||||||
|
"Calculations.Options.min.label": "Min",
|
||||||
|
"Calculations.Options.none.displayName": "Kalkulèr",
|
||||||
|
"Calculations.Options.none.label": "Ingen",
|
||||||
|
"Calculations.Options.percentChecked.displayName": "Valgt",
|
||||||
|
"Calculations.Options.percentChecked.label": "Prosent valgt",
|
||||||
|
"Calculations.Options.percentUnchecked.displayName": "Ikke valgt",
|
||||||
|
"Calculations.Options.percentUnchecked.label": "Prosent ikke valgt",
|
||||||
|
"Calculations.Options.range.displayName": "Tidsrom",
|
||||||
|
"Calculations.Options.range.label": "Tidsrom",
|
||||||
|
"Calculations.Options.sum.displayName": "Sum",
|
||||||
|
"Calculations.Options.sum.label": "Sum",
|
||||||
|
"CalendarCard.untitled": "Uten navn",
|
||||||
|
"CardActionsMenu.copiedLink": "Kopiert!",
|
||||||
|
"CardActionsMenu.copyLink": "Kopier lenke",
|
||||||
|
"CardActionsMenu.delete": "Slett",
|
||||||
|
"CardActionsMenu.duplicate": "Dupliser",
|
||||||
|
"CardBadges.title-checkboxes": "Avkrysningsbokser",
|
||||||
|
"CardBadges.title-comments": "Kommentarer",
|
||||||
|
"CardBadges.title-description": "Dette kortet har en beskrivelsestekst",
|
||||||
|
"CardDetail.Attach": "Legg ved",
|
||||||
|
"CardDetail.Follow": "Følg",
|
||||||
|
"CardDetail.Following": "Følger",
|
||||||
|
"CardDetail.add-content": "Legg til innhold",
|
||||||
|
"CardDetail.add-icon": "Legg til ikon",
|
||||||
|
"CardDetail.add-property": "+ Legg til en verdi",
|
||||||
|
"CardDetail.addCardText": "legg inn tekst i kortet",
|
||||||
|
"CardDetail.limited-body": "Oppgrader til vår profesjonelle eller bedriftsplan.",
|
||||||
|
"CardDetail.limited-button": "Oppgrader",
|
||||||
|
"CardDetail.limited-title": "Dette kortet er skjult",
|
||||||
|
"CardDetail.moveContent": "Flytt innholdet",
|
||||||
|
"CardDetail.new-comment-placeholder": "Legg til kommentar ...",
|
||||||
|
"CardDetailProperty.confirm-delete-heading": "Bekreft sletting av verdi",
|
||||||
|
"CardDetailProperty.confirm-delete-subtext": "Er du sikker på at du vil slette verdien \"{propertyName}\"? Dette vil fjerne verdien fra alle kortene på denne tavlen.",
|
||||||
|
"CardDetailProperty.confirm-property-name-change-subtext": "Er du sikker på at du vil endre verdien \"{propertyName}\" {customText}? Dette vil påvirke verdien på {numOfCards} kort på denne tavlen, og kan forårsake at du mister informasjon.",
|
||||||
|
"CardDetailProperty.confirm-property-type-change": "Bekreft endring av verditype",
|
||||||
|
"CardDetailProperty.delete-action-button": "Slett",
|
||||||
|
"CardDetailProperty.property-change-action-button": "Endre verdi",
|
||||||
|
"CardDetailProperty.property-changed": "Verdi endret!",
|
||||||
|
"CardDetailProperty.property-deleted": "Fjernet {propertyName}!",
|
||||||
|
"CardDetailProperty.property-name-change-subtext": "type fra \"{oldPropType}\" til \"{newPropType}\"",
|
||||||
|
"CardDetial.limited-link": "Lær mer om våre planer.",
|
||||||
|
"CardDialog.delete-confirmation-dialog-attachment": "Bekreft sletting av vedlegg",
|
||||||
|
"CardDialog.delete-confirmation-dialog-button-text": "Slett",
|
||||||
|
"CardDialog.delete-confirmation-dialog-heading": "Bekreft sletting av kort",
|
||||||
|
"CardDialog.editing-template": "Du redigerer en mal.",
|
||||||
|
"CardDialog.nocard": "Dette kortet eksisterer ikke eller du har ikke tilgang.",
|
||||||
|
"Categories.CreateCategoryDialog.CancelText": "Avbryt",
|
||||||
|
"Categories.CreateCategoryDialog.CreateText": "Opprett",
|
||||||
|
"Categories.CreateCategoryDialog.Placeholder": "Navngi kategorien",
|
||||||
|
"Categories.CreateCategoryDialog.UpdateText": "Oppdater",
|
||||||
|
"CenterPanel.Login": "Logg inn",
|
||||||
|
"CenterPanel.Share": "Del",
|
||||||
|
"ChannelIntro.CreateBoard": "Opprett tavle",
|
||||||
|
"CloudMessage.cloud-server": "Få din egen gratis skytjener.",
|
||||||
|
"ColorOption.selectColor": "Velg {color} farge",
|
||||||
|
"Comment.delete": "Slett",
|
||||||
|
"CommentsList.send": "Send",
|
||||||
|
"ConfirmPerson.empty": "Tom",
|
||||||
|
"ConfirmPerson.search": "Søk ...",
|
||||||
|
"ConfirmationDialog.cancel-action": "Avbryt",
|
||||||
|
"ConfirmationDialog.confirm-action": "Bekreft",
|
||||||
|
"ContentBlock.Delete": "Slett",
|
||||||
|
"ContentBlock.DeleteAction": "slett",
|
||||||
|
"ContentBlock.addElement": "legg til {type}",
|
||||||
|
"ContentBlock.checkbox": "avkrysningsboks",
|
||||||
|
"ContentBlock.divider": "avdeler",
|
||||||
|
"ContentBlock.editCardCheckbox": "krysset-boks",
|
||||||
|
"ContentBlock.editCardCheckboxText": "rediger kort tekst",
|
||||||
|
"ContentBlock.editCardText": "rediger kort tekst",
|
||||||
|
"ContentBlock.editText": "Rediger tekst ...",
|
||||||
|
"ContentBlock.image": "bilde",
|
||||||
|
"ContentBlock.insertAbove": "Sett inn over",
|
||||||
|
"ContentBlock.moveBlock": "flytt kort innhold",
|
||||||
|
"ContentBlock.moveDown": "Flytt ned",
|
||||||
|
"ContentBlock.moveUp": "Flytt opp",
|
||||||
|
"ContentBlock.text": "tekst",
|
||||||
|
"DateRange.clear": "Tøm",
|
||||||
|
"DateRange.empty": "Tom",
|
||||||
|
"DateRange.endDate": "Sluttdato",
|
||||||
|
"DateRange.today": "I dag",
|
||||||
|
"DeleteBoardDialog.confirm-cancel": "Avbryt",
|
||||||
|
"DeleteBoardDialog.confirm-delete": "Slett",
|
||||||
|
"DeleteBoardDialog.confirm-info": "Er du sikker på at du vil slette tavlen \"{boardTitle}\"? Dette vil slette alle kortene på tavlen.",
|
||||||
|
"DeleteBoardDialog.confirm-info-template": "Er du sikker på at du vil slette tavlemalen \"{boardTitle}\"?",
|
||||||
|
"DeleteBoardDialog.confirm-tite": "Bekreft sletting av tavle",
|
||||||
|
"DeleteBoardDialog.confirm-tite-template": "Bekreft sletting av tavlemal",
|
||||||
|
"Dialog.closeDialog": "Lukk",
|
||||||
|
"EditableDayPicker.today": "I dag",
|
||||||
|
"Error.mobileweb": "Støtte for bruk i nettleser på mobil er i tidlig beta. Alt vil ikke fungere.",
|
||||||
|
"Error.websocket-closed": "Problemer med kobling til tjeneren. Sjekk konfigurasjonen hvis problemet vedvarer.",
|
||||||
|
"Filter.contains": "inneholder",
|
||||||
|
"Filter.ends-with": "ender med",
|
||||||
|
"Filter.includes": "inkluderer",
|
||||||
|
"Filter.is": "er",
|
||||||
|
"Filter.is-empty": "er tom",
|
||||||
|
"Filter.is-not-empty": "er ikke tom",
|
||||||
|
"Filter.is-not-set": "er ikke satt",
|
||||||
|
"Filter.is-set": "er satt",
|
||||||
|
"Filter.not-contains": "inkluderer ikke",
|
||||||
|
"Filter.not-ends-with": "ender ikke med",
|
||||||
|
"Filter.not-includes": "inkluderer ikke",
|
||||||
|
"Filter.not-starts-with": "starter ikke med",
|
||||||
|
"Filter.starts-with": "starter med",
|
||||||
|
"FilterByText.placeholder": "filtrer tekst",
|
||||||
|
"FilterComponent.add-filter": "+ Nytt filter",
|
||||||
|
"FilterComponent.delete": "Slett",
|
||||||
|
"FilterValue.empty": "(tom)",
|
||||||
|
"FindBoardsDialog.IntroText": "Søk etter tavle",
|
||||||
|
"FindBoardsDialog.NoResultsFor": "Ingen resultat for \"{searchQuery}\"",
|
||||||
|
"FindBoardsDialog.NoResultsSubtext": "Sjekk stavingen eller søk på noe annet.",
|
||||||
|
"FindBoardsDialog.SubTitle": "Skriv for å finne en tavle. Bruk <b>opp/ned</b> for å navigere. <b>Enter</b> for å velge, eller <b>Esc</b> for å avbryte",
|
||||||
|
"FindBoardsDialog.Title": "Finn tavle",
|
||||||
|
"GroupBy.hideEmptyGroups": "Skjul {count} tomme grupper",
|
||||||
|
"GroupBy.showHiddenGroups": "Vis {count} tomme grupper",
|
||||||
|
"GroupBy.ungroup": "Fjern fra gruppe",
|
||||||
|
"HideBoard.MenuOption": "Skjul tavlen",
|
||||||
|
"KanbanCard.untitled": "Uten navn",
|
||||||
|
"Mutator.new-board-from-template": "ny tavle fra mal",
|
||||||
|
"Mutator.new-card-from-template": "nytt kort fra mal",
|
||||||
|
"Mutator.new-template-from-card": "ny mal fra kort"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
{
|
{
|
||||||
"AppBar.Tooltip": "Ativar Boards vinculados",
|
"AppBar.Tooltip": "Ativar boards vinculados",
|
||||||
|
"Attachment.Attachment-title": "Anexo",
|
||||||
|
"AttachmentBlock.DeleteAction": "apagar",
|
||||||
|
"AttachmentBlock.addElement": "adicionar {type}",
|
||||||
|
"AttachmentBlock.delete": "Anexo apagado.",
|
||||||
|
"AttachmentBlock.uploadSuccess": "Anexo enviado.",
|
||||||
|
"AttachmentElement.delete-confirmation-dialog-button-text": "Apagar",
|
||||||
|
"AttachmentElement.upload-percentage": "Enviando...({uploadPercent}%)",
|
||||||
"BoardComponent.add-a-group": "+ Adicione um grupo",
|
"BoardComponent.add-a-group": "+ Adicione um grupo",
|
||||||
"BoardComponent.delete": "Excluir",
|
"BoardComponent.delete": "Excluir",
|
||||||
"BoardComponent.hidden-columns": "Colunas ocultas",
|
"BoardComponent.hidden-columns": "Colunas ocultas",
|
||||||
@ -16,8 +23,8 @@
|
|||||||
"BoardMember.unlinkChannel": "Desvincular",
|
"BoardMember.unlinkChannel": "Desvincular",
|
||||||
"BoardPage.newVersion": "Uma nova versão do Boards está disponível, clique aqui para recarregar.",
|
"BoardPage.newVersion": "Uma nova versão do Boards está disponível, clique aqui para recarregar.",
|
||||||
"BoardPage.syncFailed": "O Board pode ter sido excluído ou o acesso revogado.",
|
"BoardPage.syncFailed": "O Board pode ter sido excluído ou o acesso revogado.",
|
||||||
"BoardTemplateSelector.add-template": "Novo modelo",
|
"BoardTemplateSelector.add-template": "Criar novo modelo",
|
||||||
"BoardTemplateSelector.create-empty-board": "Criar board vazio",
|
"BoardTemplateSelector.create-empty-board": "Criar um board vazio",
|
||||||
"BoardTemplateSelector.delete-template": "Excluir",
|
"BoardTemplateSelector.delete-template": "Excluir",
|
||||||
"BoardTemplateSelector.description": "Adicione um quadro à barra lateral usando qualquer um dos modelos definidos abaixo ou comece do zero.",
|
"BoardTemplateSelector.description": "Adicione um quadro à barra lateral usando qualquer um dos modelos definidos abaixo ou comece do zero.",
|
||||||
"BoardTemplateSelector.edit-template": "Editar",
|
"BoardTemplateSelector.edit-template": "Editar",
|
||||||
@ -25,7 +32,7 @@
|
|||||||
"BoardTemplateSelector.plugin.no-content-title": "Criar um board",
|
"BoardTemplateSelector.plugin.no-content-title": "Criar um board",
|
||||||
"BoardTemplateSelector.title": "Criar um board",
|
"BoardTemplateSelector.title": "Criar um board",
|
||||||
"BoardTemplateSelector.use-this-template": "Use este template",
|
"BoardTemplateSelector.use-this-template": "Use este template",
|
||||||
"BoardsSwitcher.Title": "Encontrar Boards",
|
"BoardsSwitcher.Title": "Encontrar boards",
|
||||||
"BoardsUnfurl.Limited": "Detalhes adicionais estão ocultos devido ao cartão ter sido arquivado",
|
"BoardsUnfurl.Limited": "Detalhes adicionais estão ocultos devido ao cartão ter sido arquivado",
|
||||||
"BoardsUnfurl.Remainder": "+{remainder} mais",
|
"BoardsUnfurl.Remainder": "+{remainder} mais",
|
||||||
"BoardsUnfurl.Updated": "Atualizado {time}",
|
"BoardsUnfurl.Updated": "Atualizado {time}",
|
||||||
@ -71,6 +78,7 @@
|
|||||||
"CardBadges.title-checkboxes": "Caixa de seleção",
|
"CardBadges.title-checkboxes": "Caixa de seleção",
|
||||||
"CardBadges.title-comments": "Comentários",
|
"CardBadges.title-comments": "Comentários",
|
||||||
"CardBadges.title-description": "Este cartão tem uma descrição",
|
"CardBadges.title-description": "Este cartão tem uma descrição",
|
||||||
|
"CardDetail.Attach": "Anexar",
|
||||||
"CardDetail.Follow": "Seguir",
|
"CardDetail.Follow": "Seguir",
|
||||||
"CardDetail.Following": "Seguindo",
|
"CardDetail.Following": "Seguindo",
|
||||||
"CardDetail.add-content": "Adicionar conteúdo",
|
"CardDetail.add-content": "Adicionar conteúdo",
|
||||||
@ -102,10 +110,13 @@
|
|||||||
"Categories.CreateCategoryDialog.UpdateText": "Atualizar",
|
"Categories.CreateCategoryDialog.UpdateText": "Atualizar",
|
||||||
"CenterPanel.Login": "Login",
|
"CenterPanel.Login": "Login",
|
||||||
"CenterPanel.Share": "Compartilhar",
|
"CenterPanel.Share": "Compartilhar",
|
||||||
|
"ChannelIntro.CreateBoard": "Criar um board",
|
||||||
"CloudMessage.cloud-server": "Obtenha seu próprio cloud server de graça.",
|
"CloudMessage.cloud-server": "Obtenha seu próprio cloud server de graça.",
|
||||||
"ColorOption.selectColor": "Selecione {color} Cor",
|
"ColorOption.selectColor": "Selecione {color} Cor",
|
||||||
"Comment.delete": "Excluir",
|
"Comment.delete": "Excluir",
|
||||||
"CommentsList.send": "Enviar",
|
"CommentsList.send": "Enviar",
|
||||||
|
"ConfirmPerson.empty": "Vazio",
|
||||||
|
"ConfirmPerson.search": "Buscar...",
|
||||||
"ConfirmationDialog.cancel-action": "Cancelar",
|
"ConfirmationDialog.cancel-action": "Cancelar",
|
||||||
"ConfirmationDialog.confirm-action": "Confirmar",
|
"ConfirmationDialog.confirm-action": "Confirmar",
|
||||||
"ContentBlock.Delete": "Excluir",
|
"ContentBlock.Delete": "Excluir",
|
||||||
@ -181,6 +192,7 @@
|
|||||||
"OnboardingTour.ShareBoard.Body": "Você pode compartilhar seu board internament, com seu time, ou public para permitir visibilidade fora da sua organização.",
|
"OnboardingTour.ShareBoard.Body": "Você pode compartilhar seu board internament, com seu time, ou public para permitir visibilidade fora da sua organização.",
|
||||||
"OnboardingTour.ShareBoard.Title": "Compartilhar quadro",
|
"OnboardingTour.ShareBoard.Title": "Compartilhar quadro",
|
||||||
"PersonProperty.board-members": "Membros do Board",
|
"PersonProperty.board-members": "Membros do Board",
|
||||||
|
"PersonProperty.me": "Eu",
|
||||||
"PersonProperty.non-board-members": "Não membros do board",
|
"PersonProperty.non-board-members": "Não membros do board",
|
||||||
"PropertyMenu.Delete": "Excluir",
|
"PropertyMenu.Delete": "Excluir",
|
||||||
"PropertyMenu.changeType": "Alterar tipo da propriedade",
|
"PropertyMenu.changeType": "Alterar tipo da propriedade",
|
||||||
@ -235,6 +247,7 @@
|
|||||||
"Sidebar.import-archive": "Importar arquivo",
|
"Sidebar.import-archive": "Importar arquivo",
|
||||||
"Sidebar.invite-users": "Convidar usuários",
|
"Sidebar.invite-users": "Convidar usuários",
|
||||||
"Sidebar.logout": "Sair",
|
"Sidebar.logout": "Sair",
|
||||||
|
"Sidebar.new-category.badge": "Novo",
|
||||||
"Sidebar.no-boards-in-category": "Nenhum board",
|
"Sidebar.no-boards-in-category": "Nenhum board",
|
||||||
"Sidebar.product-tour": "Tour pelo produto",
|
"Sidebar.product-tour": "Tour pelo produto",
|
||||||
"Sidebar.random-icons": "Ícones aleatórios",
|
"Sidebar.random-icons": "Ícones aleatórios",
|
||||||
@ -257,6 +270,7 @@
|
|||||||
"SidebarTour.SidebarCategories.Body": "Todos seus boards agora são organizados sob sua nova barra lateral. Não é mais necessárioa alternar entre espaços de trabalho. Categorias personalizadas em suas estações prévias de trabalho foram automaticamente criadas para você como parte do seu upgrade para v7.2. Estas podem ser removidas ou editadas de acordo com a sua preferência.",
|
"SidebarTour.SidebarCategories.Body": "Todos seus boards agora são organizados sob sua nova barra lateral. Não é mais necessárioa alternar entre espaços de trabalho. Categorias personalizadas em suas estações prévias de trabalho foram automaticamente criadas para você como parte do seu upgrade para v7.2. Estas podem ser removidas ou editadas de acordo com a sua preferência.",
|
||||||
"SidebarTour.SidebarCategories.Link": "Saiba mais",
|
"SidebarTour.SidebarCategories.Link": "Saiba mais",
|
||||||
"SidebarTour.SidebarCategories.Title": "Categorias de barra lateral",
|
"SidebarTour.SidebarCategories.Title": "Categorias de barra lateral",
|
||||||
|
"SiteStats.total_boards": "Total de boards",
|
||||||
"TableComponent.add-icon": "Adicionar Ícone",
|
"TableComponent.add-icon": "Adicionar Ícone",
|
||||||
"TableComponent.name": "Nome",
|
"TableComponent.name": "Nome",
|
||||||
"TableComponent.plus-new": "+ Novo",
|
"TableComponent.plus-new": "+ Novo",
|
||||||
@ -267,6 +281,7 @@
|
|||||||
"TableHeaderMenu.insert-right": "Inserir à direita",
|
"TableHeaderMenu.insert-right": "Inserir à direita",
|
||||||
"TableHeaderMenu.sort-ascending": "Ordem ascendente",
|
"TableHeaderMenu.sort-ascending": "Ordem ascendente",
|
||||||
"TableHeaderMenu.sort-descending": "Ordem descendente",
|
"TableHeaderMenu.sort-descending": "Ordem descendente",
|
||||||
|
"TableRow.MoreOption": "Mais ações",
|
||||||
"TableRow.open": "Abrir",
|
"TableRow.open": "Abrir",
|
||||||
"TopBar.give-feedback": "Dar feedback",
|
"TopBar.give-feedback": "Dar feedback",
|
||||||
"URLProperty.copiedLink": "Copiado!",
|
"URLProperty.copiedLink": "Copiado!",
|
||||||
@ -348,6 +363,7 @@
|
|||||||
"calendar.month": "Mês",
|
"calendar.month": "Mês",
|
||||||
"calendar.today": "HOJE",
|
"calendar.today": "HOJE",
|
||||||
"calendar.week": "Semana",
|
"calendar.week": "Semana",
|
||||||
|
"centerPanel.unknown-user": "Usuário desconhecido",
|
||||||
"cloudMessage.learn-more": "Saiba mais",
|
"cloudMessage.learn-more": "Saiba mais",
|
||||||
"createImageBlock.failed": "Não foi possível enviar o arquivo. Limite de tamanho alcançado.",
|
"createImageBlock.failed": "Não foi possível enviar o arquivo. Limite de tamanho alcançado.",
|
||||||
"default-properties.badges": "Comentários e descrição",
|
"default-properties.badges": "Comentários e descrição",
|
||||||
@ -369,6 +385,7 @@
|
|||||||
"login.log-in-button": "Entrar",
|
"login.log-in-button": "Entrar",
|
||||||
"login.log-in-title": "Entrar",
|
"login.log-in-title": "Entrar",
|
||||||
"login.register-button": "ou criar uma conta se você ainda não tiver uma",
|
"login.register-button": "ou criar uma conta se você ainda não tiver uma",
|
||||||
|
"new_channel_modal.create_board.select_template_placeholder": "Selecionar um modelo",
|
||||||
"notification-box-card-limit-reached.close-tooltip": "Soneca por 10 dias",
|
"notification-box-card-limit-reached.close-tooltip": "Soneca por 10 dias",
|
||||||
"notification-box-card-limit-reached.contact-link": "notificar seu admin",
|
"notification-box-card-limit-reached.contact-link": "notificar seu admin",
|
||||||
"notification-box-card-limit-reached.link": "Atualizar para um plano pago",
|
"notification-box-card-limit-reached.link": "Atualizar para um plano pago",
|
||||||
@ -388,14 +405,14 @@
|
|||||||
"rhs-boards.dm": "DM",
|
"rhs-boards.dm": "DM",
|
||||||
"rhs-boards.gm": "GM",
|
"rhs-boards.gm": "GM",
|
||||||
"rhs-boards.header.dm": "esta Direct Message",
|
"rhs-boards.header.dm": "esta Direct Message",
|
||||||
"rhs-boards.header.gm": "Este Gruop Message",
|
"rhs-boards.header.gm": "esta mensagem de grupo",
|
||||||
"rhs-boards.last-update-at": "Última atualização em: {datetime}",
|
"rhs-boards.last-update-at": "Última atualização em: {datetime}",
|
||||||
"rhs-boards.link-boards-to-channel": "Vincular boards para {channelName}",
|
"rhs-boards.link-boards-to-channel": "Vincular boards para {channelName}",
|
||||||
"rhs-boards.linked-boards": "Boards vinculados",
|
"rhs-boards.linked-boards": "Boards vinculados",
|
||||||
"rhs-boards.no-boards-linked-to-channel": "Nenhum board está vinculado a {channelName} ainda",
|
"rhs-boards.no-boards-linked-to-channel": "Nenhum board está vinculado a {channelName} ainda",
|
||||||
"rhs-boards.no-boards-linked-to-channel-description": "Boards é uma ferramenta de gerenciamento de projeto que ajuda a definir, organizar, rastrear e gerenciar o trabalho entre times, usando uma visualização de quadro estilo Kaban familiar.",
|
"rhs-boards.no-boards-linked-to-channel-description": "Boards é uma ferramenta de gerenciamento de projeto que ajuda a definir, organizar, rastrear e gerenciar o trabalho entre times, usando uma visualização de quadro estilo Kaban familiar.",
|
||||||
"rhs-boards.unlink-board": "Desvincular board",
|
"rhs-boards.unlink-board": "Desvincular board",
|
||||||
"rhs-boards.unlink-board1": "Desvincular board Hello",
|
"rhs-boards.unlink-board1": "Desvincular board",
|
||||||
"rhs-channel-boards-header.title": "Boards",
|
"rhs-channel-boards-header.title": "Boards",
|
||||||
"share-board.publish": "Publicar",
|
"share-board.publish": "Publicar",
|
||||||
"share-board.share": "Compartilhar",
|
"share-board.share": "Compartilhar",
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
"AppBar.Tooltip": "Переключить связанные доски",
|
"AppBar.Tooltip": "Переключить связанные доски",
|
||||||
"Attachment.Attachment-title": "Вложение",
|
"Attachment.Attachment-title": "Вложение",
|
||||||
"AttachmentBlock.DeleteAction": "Удалить",
|
"AttachmentBlock.DeleteAction": "Удалить",
|
||||||
"AttachmentBlock.addElement": "добавить",
|
"AttachmentBlock.addElement": "добавить {type}",
|
||||||
"AttachmentBlock.delete": "Вложение успешно удалено.",
|
"AttachmentBlock.delete": "Вложение удалено.",
|
||||||
"AttachmentBlock.failed": "Не удалось загрузить файл. Достигнут предел размера вложения.",
|
"AttachmentBlock.failed": "Не удалось загрузить файл, так как превышена квота на размер файла.",
|
||||||
"AttachmentBlock.upload": "Загрузка вложения.",
|
"AttachmentBlock.upload": "Загрузка вложения.",
|
||||||
"AttachmentBlock.uploadSuccess": "Вложение успешно загружено.",
|
"AttachmentBlock.uploadSuccess": "Вложение загружено.",
|
||||||
"AttachmentElement.delete-confirmation-dialog-button-text": "Удалить",
|
"AttachmentElement.delete-confirmation-dialog-button-text": "Удалить",
|
||||||
"AttachmentElement.download": "Скачать",
|
"AttachmentElement.download": "Скачать",
|
||||||
"AttachmentElement.upload-percentage": "Загрузка",
|
"AttachmentElement.upload-percentage": "Загрузка...({uploadPercent}%)",
|
||||||
"BoardComponent.add-a-group": "+ Добавить группу",
|
"BoardComponent.add-a-group": "+ Добавить группу",
|
||||||
"BoardComponent.delete": "Удалить",
|
"BoardComponent.delete": "Удалить",
|
||||||
"BoardComponent.hidden-columns": "Скрытые столбцы",
|
"BoardComponent.hidden-columns": "Скрытые столбцы",
|
||||||
@ -31,12 +31,12 @@
|
|||||||
"BoardTemplateSelector.delete-template": "Удалить",
|
"BoardTemplateSelector.delete-template": "Удалить",
|
||||||
"BoardTemplateSelector.description": "Добавьте доску на боковую панель, используя любой из шаблонов, описанных ниже, или начните с нуля.",
|
"BoardTemplateSelector.description": "Добавьте доску на боковую панель, используя любой из шаблонов, описанных ниже, или начните с нуля.",
|
||||||
"BoardTemplateSelector.edit-template": "Изменить",
|
"BoardTemplateSelector.edit-template": "Изменить",
|
||||||
"BoardTemplateSelector.plugin.no-content-description": "Добавьте доску на боковую панель, используя любой из указанных ниже шаблонов, или начните с нуля.{lineBreak} Участники \"{teamName}\" будут иметь доступ к созданным здесь доскам.",
|
"BoardTemplateSelector.plugin.no-content-description": "Добавьте доску на боковую панель, используя любой из указанных ниже шаблонов, или начните с нуля.",
|
||||||
"BoardTemplateSelector.plugin.no-content-title": "Создать доску",
|
"BoardTemplateSelector.plugin.no-content-title": "Создать доску",
|
||||||
"BoardTemplateSelector.title": "Создать доску",
|
"BoardTemplateSelector.title": "Создать доску",
|
||||||
"BoardTemplateSelector.use-this-template": "Использовать этот шаблон",
|
"BoardTemplateSelector.use-this-template": "Использовать этот шаблон",
|
||||||
"BoardsSwitcher.Title": "Найти доски",
|
"BoardsSwitcher.Title": "Найти доски",
|
||||||
"BoardsUnfurl.Limited": "Информация скрыта в связи с тем, что карточка находится в архиве",
|
"BoardsUnfurl.Limited": "Информация скрыта, потому что карточка находится в архиве",
|
||||||
"BoardsUnfurl.Remainder": "+{remainder} ещё",
|
"BoardsUnfurl.Remainder": "+{remainder} ещё",
|
||||||
"BoardsUnfurl.Updated": "Обновлено {time}",
|
"BoardsUnfurl.Updated": "Обновлено {time}",
|
||||||
"Calculations.Options.average.displayName": "Среднее",
|
"Calculations.Options.average.displayName": "Среднее",
|
||||||
@ -103,9 +103,9 @@
|
|||||||
"CardDetailProperty.property-deleted": "{propertyName} успешно удалено!",
|
"CardDetailProperty.property-deleted": "{propertyName} успешно удалено!",
|
||||||
"CardDetailProperty.property-name-change-subtext": "тип из \"{oldPropType}\" в \"{newPropType}\"",
|
"CardDetailProperty.property-name-change-subtext": "тип из \"{oldPropType}\" в \"{newPropType}\"",
|
||||||
"CardDetial.limited-link": "Узнайте больше о наших планах.",
|
"CardDetial.limited-link": "Узнайте больше о наших планах.",
|
||||||
"CardDialog.delete-confirmation-dialog-attachment": "Подтвердите удаление вложения!",
|
"CardDialog.delete-confirmation-dialog-attachment": "Подтвердите удаление вложения",
|
||||||
"CardDialog.delete-confirmation-dialog-button-text": "Удалить",
|
"CardDialog.delete-confirmation-dialog-button-text": "Удалить",
|
||||||
"CardDialog.delete-confirmation-dialog-heading": "Подтвердите удаление карточки!",
|
"CardDialog.delete-confirmation-dialog-heading": "Подтвердите удаление карточки",
|
||||||
"CardDialog.editing-template": "Вы редактируете шаблон.",
|
"CardDialog.editing-template": "Вы редактируете шаблон.",
|
||||||
"CardDialog.nocard": "Эта карточка не существует или недоступна.",
|
"CardDialog.nocard": "Эта карточка не существует или недоступна.",
|
||||||
"Categories.CreateCategoryDialog.CancelText": "Отмена",
|
"Categories.CreateCategoryDialog.CancelText": "Отмена",
|
||||||
@ -114,10 +114,13 @@
|
|||||||
"Categories.CreateCategoryDialog.UpdateText": "Обновить",
|
"Categories.CreateCategoryDialog.UpdateText": "Обновить",
|
||||||
"CenterPanel.Login": "Логин",
|
"CenterPanel.Login": "Логин",
|
||||||
"CenterPanel.Share": "Поделиться",
|
"CenterPanel.Share": "Поделиться",
|
||||||
|
"ChannelIntro.CreateBoard": "Создать доску",
|
||||||
"CloudMessage.cloud-server": "Получите свой бесплатный облачный сервер.",
|
"CloudMessage.cloud-server": "Получите свой бесплатный облачный сервер.",
|
||||||
"ColorOption.selectColor": "Выберите цвет {color}",
|
"ColorOption.selectColor": "Выберите цвет {color}",
|
||||||
"Comment.delete": "Удалить",
|
"Comment.delete": "Удалить",
|
||||||
"CommentsList.send": "Отправить",
|
"CommentsList.send": "Отправить",
|
||||||
|
"ConfirmPerson.empty": "Пусто",
|
||||||
|
"ConfirmPerson.search": "Поиск...",
|
||||||
"ConfirmationDialog.cancel-action": "Отмена",
|
"ConfirmationDialog.cancel-action": "Отмена",
|
||||||
"ConfirmationDialog.confirm-action": "Подтвердить",
|
"ConfirmationDialog.confirm-action": "Подтвердить",
|
||||||
"ContentBlock.Delete": "Удалить",
|
"ContentBlock.Delete": "Удалить",
|
||||||
@ -165,6 +168,7 @@
|
|||||||
"FilterByText.placeholder": "фильтровать текст",
|
"FilterByText.placeholder": "фильтровать текст",
|
||||||
"FilterComponent.add-filter": "+ Добавить фильтр",
|
"FilterComponent.add-filter": "+ Добавить фильтр",
|
||||||
"FilterComponent.delete": "Удалить",
|
"FilterComponent.delete": "Удалить",
|
||||||
|
"FilterValue.empty": "(пусто)",
|
||||||
"FindBoardsDialog.IntroText": "Поиск досок",
|
"FindBoardsDialog.IntroText": "Поиск досок",
|
||||||
"FindBoardsDialog.NoResultsFor": "Нет результатов для \"{searchQuery}\"",
|
"FindBoardsDialog.NoResultsFor": "Нет результатов для \"{searchQuery}\"",
|
||||||
"FindBoardsDialog.NoResultsSubtext": "Проверьте правильность написания или попробуйте другой запрос.",
|
"FindBoardsDialog.NoResultsSubtext": "Проверьте правильность написания или попробуйте другой запрос.",
|
||||||
@ -183,7 +187,7 @@
|
|||||||
"OnboardingTour.AddComments.Title": "Добавить комментарии",
|
"OnboardingTour.AddComments.Title": "Добавить комментарии",
|
||||||
"OnboardingTour.AddDescription.Body": "Добавьте описание к своей карточке, чтобы Ваши коллеги по команде знали, о чем эта карточка.",
|
"OnboardingTour.AddDescription.Body": "Добавьте описание к своей карточке, чтобы Ваши коллеги по команде знали, о чем эта карточка.",
|
||||||
"OnboardingTour.AddDescription.Title": "Добавить описание",
|
"OnboardingTour.AddDescription.Title": "Добавить описание",
|
||||||
"OnboardingTour.AddProperties.Body": "Добавляйте различные свойства карточкам, чтобы сделать их более мощными!",
|
"OnboardingTour.AddProperties.Body": "Добавляйте различные свойства карточкам, чтобы сделать их более значительными.",
|
||||||
"OnboardingTour.AddProperties.Title": "Добавить свойства",
|
"OnboardingTour.AddProperties.Title": "Добавить свойства",
|
||||||
"OnboardingTour.AddView.Body": "Перейдите сюда, чтобы создать новый вид для организации доски с использованием различных макетов.",
|
"OnboardingTour.AddView.Body": "Перейдите сюда, чтобы создать новый вид для организации доски с использованием различных макетов.",
|
||||||
"OnboardingTour.AddView.Title": "Добавить новый вид",
|
"OnboardingTour.AddView.Title": "Добавить новый вид",
|
||||||
@ -284,6 +288,7 @@
|
|||||||
"TableHeaderMenu.insert-right": "Вставить справа",
|
"TableHeaderMenu.insert-right": "Вставить справа",
|
||||||
"TableHeaderMenu.sort-ascending": "Сортировать по возрастанию",
|
"TableHeaderMenu.sort-ascending": "Сортировать по возрастанию",
|
||||||
"TableHeaderMenu.sort-descending": "Сортировать по убыванию",
|
"TableHeaderMenu.sort-descending": "Сортировать по убыванию",
|
||||||
|
"TableRow.DuplicateCard": "дублировать карточку",
|
||||||
"TableRow.MoreOption": "Больше действий",
|
"TableRow.MoreOption": "Больше действий",
|
||||||
"TableRow.open": "Открыть",
|
"TableRow.open": "Открыть",
|
||||||
"TopBar.give-feedback": "Дать обратную связь",
|
"TopBar.give-feedback": "Дать обратную связь",
|
||||||
@ -351,10 +356,13 @@
|
|||||||
"WelcomePage.Explore.Button": "Исследовать",
|
"WelcomePage.Explore.Button": "Исследовать",
|
||||||
"WelcomePage.Heading": "Добро пожаловать на Доски",
|
"WelcomePage.Heading": "Добро пожаловать на Доски",
|
||||||
"WelcomePage.NoThanks.Text": "Нет спасибо, сам разберусь",
|
"WelcomePage.NoThanks.Text": "Нет спасибо, сам разберусь",
|
||||||
|
"WelcomePage.StartUsingIt.Text": "Начать пользоваться",
|
||||||
"Workspace.editing-board-template": "Вы редактируете шаблон доски.",
|
"Workspace.editing-board-template": "Вы редактируете шаблон доски.",
|
||||||
|
"badge.guest": "Гость",
|
||||||
"boardSelector.confirm-link-board": "Привязать доску к каналу",
|
"boardSelector.confirm-link-board": "Привязать доску к каналу",
|
||||||
"boardSelector.confirm-link-board-button": "Да, ссылка доски",
|
"boardSelector.confirm-link-board-button": "Да, ссылка доски",
|
||||||
"boardSelector.confirm-link-board-subtext": "Связывание доски \"{boardName}\" с этим каналом даст всем участникам этого канала доступ на редактирование доски. Вы уверены, что хотите связать это?",
|
"boardSelector.confirm-link-board-subtext": "Связывание доски \"{boardName}\" с каналом даст всем участникам канала доступ на редактирование доски. Вы можете в любое время отвязать доску о канала.",
|
||||||
|
"boardSelector.confirm-link-board-subtext-with-other-channel": "Привязка \"{boardName}\" с каналом приведет к возможности её редактирования всеми участниками канала (существующими и новыми). Кроме гостей канала.{lineBreak} Эта доска сейчас связана с другим каналом. Он будет отключен, если вы решите изменить привязку.",
|
||||||
"boardSelector.create-a-board": "Создать доску",
|
"boardSelector.create-a-board": "Создать доску",
|
||||||
"boardSelector.link": "Ссылка",
|
"boardSelector.link": "Ссылка",
|
||||||
"boardSelector.search-for-boards": "Поиск досок",
|
"boardSelector.search-for-boards": "Поиск досок",
|
||||||
@ -363,6 +371,8 @@
|
|||||||
"calendar.month": "Месяц",
|
"calendar.month": "Месяц",
|
||||||
"calendar.today": "СЕГОДНЯ",
|
"calendar.today": "СЕГОДНЯ",
|
||||||
"calendar.week": "Неделя",
|
"calendar.week": "Неделя",
|
||||||
|
"centerPanel.undefined": "Отсутствует {propertyName}",
|
||||||
|
"centerPanel.unknown-user": "Неизвестный пользователь",
|
||||||
"cloudMessage.learn-more": "Учить больше",
|
"cloudMessage.learn-more": "Учить больше",
|
||||||
"createImageBlock.failed": "Не удалось загрузить файл. Достигнут предел размера файла.",
|
"createImageBlock.failed": "Не удалось загрузить файл. Достигнут предел размера файла.",
|
||||||
"default-properties.badges": "Комментарии и описание",
|
"default-properties.badges": "Комментарии и описание",
|
||||||
@ -377,11 +387,15 @@
|
|||||||
"error.team-undefined": "Не корректная команда.",
|
"error.team-undefined": "Не корректная команда.",
|
||||||
"error.unknown": "Произошла ошибка.",
|
"error.unknown": "Произошла ошибка.",
|
||||||
"generic.previous": "Предыдущий",
|
"generic.previous": "Предыдущий",
|
||||||
"imagePaste.upload-failed": "Некоторые файлы не загружены. Достигнут предел размера файла",
|
"imagePaste.upload-failed": "Некоторые файлы не загружены из-за превышения квоты на размер файла.",
|
||||||
"limitedCard.title": "Карточки скрыты",
|
"limitedCard.title": "Карточки скрыты",
|
||||||
"login.log-in-button": "Вход в систему",
|
"login.log-in-button": "Вход в систему",
|
||||||
"login.log-in-title": "Вход в систему",
|
"login.log-in-title": "Вход в систему",
|
||||||
"login.register-button": "или создать аккаунт, если у Вас его нет",
|
"login.register-button": "или создать аккаунт, если у Вас его нет",
|
||||||
|
"new_channel_modal.create_board.empty_board_description": "Создать новую пустую доску",
|
||||||
|
"new_channel_modal.create_board.empty_board_title": "Пустая доска",
|
||||||
|
"new_channel_modal.create_board.select_template_placeholder": "Выбрать шаблон",
|
||||||
|
"new_channel_modal.create_board.title": "Создать доску для этого канала",
|
||||||
"notification-box-card-limit-reached.close-tooltip": "Отложить на 10 дней",
|
"notification-box-card-limit-reached.close-tooltip": "Отложить на 10 дней",
|
||||||
"notification-box-card-limit-reached.contact-link": "уведомить Вашего администратора",
|
"notification-box-card-limit-reached.contact-link": "уведомить Вашего администратора",
|
||||||
"notification-box-card-limit-reached.link": "Перейти на платный тариф",
|
"notification-box-card-limit-reached.link": "Перейти на платный тариф",
|
||||||
@ -389,13 +403,18 @@
|
|||||||
"notification-box-cards-hidden.title": "Это действие скрыло другую карточку",
|
"notification-box-cards-hidden.title": "Это действие скрыло другую карточку",
|
||||||
"notification-box.card-limit-reached.not-admin.text": "Чтобы получить доступ к архивным карточкам, Вы можете {contactLink} перейти на платный тариф.",
|
"notification-box.card-limit-reached.not-admin.text": "Чтобы получить доступ к архивным карточкам, Вы можете {contactLink} перейти на платный тариф.",
|
||||||
"notification-box.card-limit-reached.text": "Достигнут лимит карточки, чтобы просмотреть старые карточки, {link}",
|
"notification-box.card-limit-reached.text": "Достигнут лимит карточки, чтобы просмотреть старые карточки, {link}",
|
||||||
|
"person.add-user-to-board": "Добавить {username} на доску",
|
||||||
|
"person.add-user-to-board-confirm-button": "Добавить доску",
|
||||||
|
"person.add-user-to-board-permissions": "Разрешения",
|
||||||
|
"person.add-user-to-board-question": "Вы хотите добавить {username} на доску?",
|
||||||
"register.login-button": "или войти в систему, если у вас уже есть аккаунт",
|
"register.login-button": "или войти в систему, если у вас уже есть аккаунт",
|
||||||
"register.signup-title": "Зарегистрируйте свой аккаунт",
|
"register.signup-title": "Зарегистрируйте свой аккаунт",
|
||||||
|
"rhs-board-non-admin-msg": "Вы не являетесь администратором этой доски",
|
||||||
"rhs-boards.add": "Добавить",
|
"rhs-boards.add": "Добавить",
|
||||||
"rhs-boards.last-update-at": "Последнее обновление: {datetime}",
|
"rhs-boards.last-update-at": "Последнее обновление: {datetime}",
|
||||||
"rhs-boards.link-boards-to-channel": "Связать доски с {channelName}",
|
"rhs-boards.link-boards-to-channel": "Связать доски с {channelName}",
|
||||||
"rhs-boards.linked-boards": "Связанные доски",
|
"rhs-boards.linked-boards": "Связанные доски",
|
||||||
"rhs-boards.no-boards-linked-to-channel": "К каналу {channelName} пока не подключены доски.",
|
"rhs-boards.no-boards-linked-to-channel": "К каналу {channelName} пока не подключены доски",
|
||||||
"rhs-boards.no-boards-linked-to-channel-description": "Доски — это инструмент управления проектами, который помогает определять, организовывать, отслеживать и управлять работой между командами, используя знакомое представление доски Канбан.",
|
"rhs-boards.no-boards-linked-to-channel-description": "Доски — это инструмент управления проектами, который помогает определять, организовывать, отслеживать и управлять работой между командами, используя знакомое представление доски Канбан.",
|
||||||
"rhs-boards.unlink-board": "Отвязать доску",
|
"rhs-boards.unlink-board": "Отвязать доску",
|
||||||
"rhs-channel-boards-header.title": "Доски",
|
"rhs-channel-boards-header.title": "Доски",
|
||||||
|
4
webapp/package-lock.json
generated
4
webapp/package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "focalboard",
|
"name": "focalboard",
|
||||||
"version": "7.9.0",
|
"version": "7.10.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "focalboard",
|
"name": "focalboard",
|
||||||
"version": "7.9.0",
|
"version": "7.10.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@draft-js-plugins/editor": "^4.1.2",
|
"@draft-js-plugins/editor": "^4.1.2",
|
||||||
"@draft-js-plugins/emoji": "^4.6.0",
|
"@draft-js-plugins/emoji": "^4.6.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "focalboard",
|
"name": "focalboard",
|
||||||
"version": "7.9.0",
|
"version": "7.10.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -10,7 +10,7 @@ exports[`components/sidebar/GlobalHeader header menu should match snapshot 1`] =
|
|||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
class="GlobalHeaderComponent__button help-button"
|
class="GlobalHeaderComponent__button help-button"
|
||||||
href="https://www.focalboard.com/fwlink/doc-boards.html?v=7.9.0"
|
href="https://www.focalboard.com/fwlink/doc-boards.html?v=7.10.0"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
|
@ -51,9 +51,9 @@ exports[`components/sidebarSidebar dont show hidden boards 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="version"
|
class="version"
|
||||||
title="v7.9.0"
|
title="v7.10.0"
|
||||||
>
|
>
|
||||||
v7.9.0
|
v7.10.0
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -252,9 +252,9 @@ exports[`components/sidebarSidebar should assign default category if current boa
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="version"
|
class="version"
|
||||||
title="v7.9.0"
|
title="v7.10.0"
|
||||||
>
|
>
|
||||||
v7.9.0
|
v7.10.0
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -508,9 +508,9 @@ exports[`components/sidebarSidebar shouldnt do any category assignment is board
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="version"
|
class="version"
|
||||||
title="v7.9.0"
|
title="v7.10.0"
|
||||||
>
|
>
|
||||||
v7.9.0
|
v7.10.0
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -919,9 +919,9 @@ exports[`components/sidebarSidebar sidebar hidden 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="version"
|
class="version"
|
||||||
title="v7.9.0"
|
title="v7.10.0"
|
||||||
>
|
>
|
||||||
v7.9.0
|
v7.10.0
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1213,9 +1213,9 @@ exports[`components/sidebarSidebar some categories hidden 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="version"
|
class="version"
|
||||||
title="v7.9.0"
|
title="v7.10.0"
|
||||||
>
|
>
|
||||||
v7.9.0
|
v7.10.0
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -203,6 +203,7 @@
|
|||||||
width: inherit;
|
width: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MultiPerson.octo-propertyvalue,
|
||||||
.Person.octo-propertyvalue,
|
.Person.octo-propertyvalue,
|
||||||
.DateRange.octo-propertyvalue {
|
.DateRange.octo-propertyvalue {
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
|
@ -37,8 +37,8 @@ class Constants {
|
|||||||
static readonly titleColumnId = '__title'
|
static readonly titleColumnId = '__title'
|
||||||
static readonly badgesColumnId = '__badges'
|
static readonly badgesColumnId = '__badges'
|
||||||
|
|
||||||
static readonly versionString = '7.9.0'
|
static readonly versionString = '7.10.0'
|
||||||
static readonly versionDisplayString = 'Mar 2023'
|
static readonly versionDisplayString = 'Apr 2023'
|
||||||
|
|
||||||
static readonly archiveHelpPage = 'https://docs.mattermost.com/boards/migrate-to-boards.html'
|
static readonly archiveHelpPage = 'https://docs.mattermost.com/boards/migrate-to-boards.html'
|
||||||
static readonly imports = [
|
static readonly imports = [
|
||||||
|
@ -18,6 +18,9 @@ exports[`pages/welcome Welcome Page shows Explore Page 1`] = `
|
|||||||
>
|
>
|
||||||
Boards is a project management tool that helps define, organize, track, and manage work across teams using a familiar Kanban board view.
|
Boards is a project management tool that helps define, organize, track, and manage work across teams using a familiar Kanban board view.
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="WelcomePage__content"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
alt="Boards Welcome Image"
|
alt="Boards Welcome Image"
|
||||||
class="WelcomePage__image WelcomePage__image--large"
|
class="WelcomePage__image WelcomePage__image--large"
|
||||||
@ -28,6 +31,9 @@ exports[`pages/welcome Welcome Page shows Explore Page 1`] = `
|
|||||||
class="WelcomePage__image WelcomePage__image--small"
|
class="WelcomePage__image WelcomePage__image--small"
|
||||||
src="test-file-stub"
|
src="test-file-stub"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
class="WelcomePage__buttons"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="Button filled size--large"
|
class="Button filled size--large"
|
||||||
type="button"
|
type="button"
|
||||||
@ -47,6 +53,8 @@ exports[`pages/welcome Welcome Page shows Explore Page 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`pages/welcome Welcome Page shows Explore Page with subpath 1`] = `
|
exports[`pages/welcome Welcome Page shows Explore Page with subpath 1`] = `
|
||||||
@ -67,6 +75,9 @@ exports[`pages/welcome Welcome Page shows Explore Page with subpath 1`] = `
|
|||||||
>
|
>
|
||||||
Boards is a project management tool that helps define, organize, track, and manage work across teams using a familiar Kanban board view.
|
Boards is a project management tool that helps define, organize, track, and manage work across teams using a familiar Kanban board view.
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="WelcomePage__content"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
alt="Boards Welcome Image"
|
alt="Boards Welcome Image"
|
||||||
class="WelcomePage__image WelcomePage__image--large"
|
class="WelcomePage__image WelcomePage__image--large"
|
||||||
@ -77,6 +88,9 @@ exports[`pages/welcome Welcome Page shows Explore Page with subpath 1`] = `
|
|||||||
class="WelcomePage__image WelcomePage__image--small"
|
class="WelcomePage__image WelcomePage__image--small"
|
||||||
src="test-file-stub"
|
src="test-file-stub"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
class="WelcomePage__buttons"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="Button filled size--large"
|
class="Button filled size--large"
|
||||||
type="button"
|
type="button"
|
||||||
@ -96,4 +110,6 @@ exports[`pages/welcome Welcome Page shows Explore Page with subpath 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -10,6 +10,26 @@
|
|||||||
@media (max-height: 768px) {
|
@media (max-height: 768px) {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
padding-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WelcomePage__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
@media (max-height: 800px) {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.WelcomePage__buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
@ -34,7 +54,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.skip {
|
.skip {
|
||||||
margin-top: 12px;
|
|
||||||
color: rgba(var(--link-color-rgb), 1);
|
color: rgba(var(--link-color-rgb), 1);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
@ -127,6 +127,7 @@ const WelcomePage = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='WelcomePage__content'>
|
||||||
{/* This image will be rendered on large screens over 2000px */}
|
{/* This image will be rendered on large screens over 2000px */}
|
||||||
<img
|
<img
|
||||||
src={Utils.buildURL(BoardWelcomePNG, true)}
|
src={Utils.buildURL(BoardWelcomePNG, true)}
|
||||||
@ -141,6 +142,7 @@ const WelcomePage = () => {
|
|||||||
alt='Boards Welcome Image'
|
alt='Boards Welcome Image'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className='WelcomePage__buttons'>
|
||||||
{me?.is_guest !== true &&
|
{me?.is_guest !== true &&
|
||||||
<Button
|
<Button
|
||||||
onClick={startTour}
|
onClick={startTour}
|
||||||
@ -182,6 +184,8 @@ const WelcomePage = () => {
|
|||||||
</Button>}
|
</Button>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,23 @@ exports[`properties/dateRange handle clear 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`properties/dateRange returns component with new date after prop change 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="DateRange octo-propertyvalue"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="Button"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
June 15
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`properties/dateRange returns default correctly 1`] = `
|
exports[`properties/dateRange returns default correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -315,4 +315,36 @@ describe('properties/dateRange', () => {
|
|||||||
|
|
||||||
expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, JSON.stringify({from: today}))
|
expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, JSON.stringify({from: today}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('returns component with new date after prop change', () => {
|
||||||
|
const component = wrapIntl(
|
||||||
|
<DateProp
|
||||||
|
property={new DateProperty()}
|
||||||
|
propertyValue=''
|
||||||
|
showEmptyPlaceholder={false}
|
||||||
|
readOnly={false}
|
||||||
|
board={{...board}}
|
||||||
|
card={{...card}}
|
||||||
|
propertyTemplate={propertyTemplate}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
const {container, rerender} = render(component)
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
wrapIntl(
|
||||||
|
<DateProp
|
||||||
|
property={new DateProperty()}
|
||||||
|
propertyValue={'{"from": ' + June15.getTime().toString() + '}'}
|
||||||
|
showEmptyPlaceholder={false}
|
||||||
|
readOnly={false}
|
||||||
|
board={{...board}}
|
||||||
|
card={{...card}}
|
||||||
|
propertyTemplate={propertyTemplate}
|
||||||
|
/>,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// 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 React, {useMemo, useState, useCallback} from 'react'
|
import React, {useMemo, useState, useCallback, useEffect} from 'react'
|
||||||
import {useIntl} from 'react-intl'
|
import {useIntl} from 'react-intl'
|
||||||
import {DateUtils} from 'react-day-picker'
|
import {DateUtils} from 'react-day-picker'
|
||||||
import MomentLocaleUtils from 'react-day-picker/moment'
|
import MomentLocaleUtils from 'react-day-picker/moment'
|
||||||
@ -58,6 +58,12 @@ function DateRange(props: PropertyProps): JSX.Element {
|
|||||||
const [value, setValue] = useState(propertyValue)
|
const [value, setValue] = useState(propertyValue)
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (value !== propertyValue) {
|
||||||
|
setValue(propertyValue)
|
||||||
|
}
|
||||||
|
}, [propertyValue, setValue])
|
||||||
|
|
||||||
const onChange = useCallback((newValue) => {
|
const onChange = useCallback((newValue) => {
|
||||||
if (value !== newValue) {
|
if (value !== newValue) {
|
||||||
setValue(newValue)
|
setValue(newValue)
|
||||||
|
@ -50,6 +50,7 @@ export const TelemetryActions = {
|
|||||||
LimitCardLimitReached: 'limit_cardLimitReached',
|
LimitCardLimitReached: 'limit_cardLimitReached',
|
||||||
LimitCardLimitLinkOpen: 'limit_cardLimitLinkOpen',
|
LimitCardLimitLinkOpen: 'limit_cardLimitLinkOpen',
|
||||||
VersionMoreInfo: 'version_more_info',
|
VersionMoreInfo: 'version_more_info',
|
||||||
|
ClickChannelsRHSBoard: 'click_board_in_channels_RHS',
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IEventProps {
|
interface IEventProps {
|
||||||
|
Loading…
Reference in New Issue
Block a user