Mono repo -> Master (#22553)
Combines the following repositories into one: https://github.com/mattermost/mattermost-server https://github.com/mattermost/mattermost-webapp https://github.com/mattermost/focalboard https://github.com/mattermost/mattermost-plugin-playbooks
Этот коммит содержится в:
8
server/channels/app/worktemplates/categories.yaml
Обычный файл
8
server/channels/app/worktemplates/categories.yaml
Обычный файл
@@ -0,0 +1,8 @@
|
||||
- id: product_teams
|
||||
name: worktemplate.category.product_teams
|
||||
- id: devops
|
||||
name: worktemplate.category.devops
|
||||
- id: companywide
|
||||
name: worktemplate.category.companywide
|
||||
- id: leadership
|
||||
name: worktemplate.category.leadership
|
||||
164
server/channels/app/worktemplates/generator/main.go
Обычный файл
164
server/channels/app/worktemplates/generator/main.go
Обычный файл
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"text/template"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/tools/imports"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/server/channels/app/worktemplates"
|
||||
)
|
||||
|
||||
type WorkTemplateWithMD5 struct {
|
||||
worktemplates.WorkTemplate
|
||||
MD5 string
|
||||
}
|
||||
|
||||
type WorkTemplateCategoryWithMD5 struct {
|
||||
worktemplates.WorkTemplateCategory `yaml:",inline"`
|
||||
MD5 string
|
||||
}
|
||||
|
||||
func getFileContent(filename string) ([]byte, error) {
|
||||
return os.ReadFile(path.Join(filename))
|
||||
}
|
||||
|
||||
func main() {
|
||||
// parse categories first
|
||||
dat, err := getFileContent("categories.yaml")
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, "failed to read categories.yaml"))
|
||||
}
|
||||
|
||||
h := md5.New()
|
||||
|
||||
cats := []WorkTemplateCategoryWithMD5{} // meow
|
||||
err = yaml.Unmarshal(dat, &cats)
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, "failed to unmarshal categories.yaml"))
|
||||
}
|
||||
|
||||
// validate categories
|
||||
categoryIds := map[string]struct{}{}
|
||||
for id := range cats {
|
||||
cat := cats[id]
|
||||
|
||||
if cat.ID == "" && cat.Name == "" {
|
||||
// skip empty array element
|
||||
continue
|
||||
}
|
||||
|
||||
if cat.ID == "" {
|
||||
log.Fatal(errors.New("category ID cannot be empty"))
|
||||
}
|
||||
if cat.Name == "" {
|
||||
log.Fatal(errors.New("category name cannot be empty"))
|
||||
}
|
||||
categoryIds[cat.ID] = struct{}{}
|
||||
|
||||
h.Write([]byte(cat.ID))
|
||||
cats[id].MD5 = fmt.Sprintf("%x", h.Sum(nil))
|
||||
h.Reset()
|
||||
}
|
||||
|
||||
dat, err = getFileContent("templates.yaml")
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, "failed to read templates.yaml"))
|
||||
}
|
||||
|
||||
dec := yaml.NewDecoder(bytes.NewReader(dat))
|
||||
ts := []WorkTemplateWithMD5{}
|
||||
for {
|
||||
t := worktemplates.WorkTemplate{}
|
||||
err = dec.Decode(&t)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
if t.ID == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
h.Write([]byte(t.ID))
|
||||
err = t.Validate(categoryIds)
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, "failed to validate template"))
|
||||
}
|
||||
|
||||
ts = append(ts, WorkTemplateWithMD5{
|
||||
WorkTemplate: t,
|
||||
MD5: fmt.Sprintf("%x", h.Sum(nil)),
|
||||
})
|
||||
h.Reset()
|
||||
}
|
||||
|
||||
code := bytes.NewBuffer(nil)
|
||||
tmpl, err := template.New("worktemplates").Parse(tpl)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
tmpl.Execute(code, struct {
|
||||
Templates []WorkTemplateWithMD5
|
||||
Categories []WorkTemplateCategoryWithMD5
|
||||
}{
|
||||
Templates: ts,
|
||||
Categories: cats,
|
||||
})
|
||||
|
||||
formattedCode, err := imports.Process(path.Join("worktemplate_generated.go"), code.Bytes(), &imports.Options{Comments: true})
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, "failed to format code"))
|
||||
}
|
||||
|
||||
err = os.WriteFile(path.Join("worktemplate_generated.go"), formattedCode, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// order ts by category alphabetically and by name alphabetically
|
||||
sort.Slice(ts, func(i, j int) bool {
|
||||
if ts[i].Category == ts[j].Category {
|
||||
return ts[i].UseCase < ts[j].UseCase
|
||||
}
|
||||
return ts[i].Category < ts[j].Category
|
||||
})
|
||||
|
||||
// print all translatable content
|
||||
fmt.Println("\nTranslation helpers:\n====================")
|
||||
for _, t := range ts {
|
||||
translationHelper(t.Description.Board)
|
||||
translationHelper(t.Description.Channel)
|
||||
translationHelper(t.Description.Integration)
|
||||
translationHelper(t.Description.Playbook)
|
||||
}
|
||||
}
|
||||
|
||||
var translationHelperTemplate = `{
|
||||
"id": %q,
|
||||
"translation": %q
|
||||
},`
|
||||
|
||||
func translationHelper(t *worktemplates.TranslatableString) {
|
||||
if t != nil && t.ID != "" && t.DefaultMessage != "" {
|
||||
fmt.Printf(translationHelperTemplate, t.ID, t.DefaultMessage)
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed worktemplate.tmpl
|
||||
var tpl string
|
||||
101
server/channels/app/worktemplates/generator/worktemplate.tmpl
Обычный файл
101
server/channels/app/worktemplates/generator/worktemplate.tmpl
Обычный файл
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Code generated by "make generate-worktemplates"
|
||||
// DO NOT EDIT
|
||||
|
||||
package worktemplates
|
||||
|
||||
func init() {
|
||||
{{- range .Categories}}
|
||||
registerWorkTemplateCategory("{{.ID}}", wtc{{.MD5}})
|
||||
{{- end -}}
|
||||
{{range .Templates}}
|
||||
registerWorkTemplate("{{.ID}}", wt{{.MD5}})
|
||||
{{- end}}
|
||||
|
||||
// Register categories strings
|
||||
{{range .Categories -}}
|
||||
_ = T("{{.Name}}")
|
||||
{{end}}
|
||||
|
||||
// Register translation strings
|
||||
{{range .Templates -}}
|
||||
{{if and (.Description.Channel) (ne .Description.Channel.ID "")}}_ = T("{{.Description.Channel.ID}}")
|
||||
{{end -}}
|
||||
{{if and (.Description.Board) (ne .Description.Board.ID "")}}_ = T("{{.Description.Board.ID}}")
|
||||
{{end -}}
|
||||
{{if and (.Description.Playbook) (ne .Description.Playbook.ID "")}}_ = T("{{.Description.Playbook.ID}}")
|
||||
{{end -}}
|
||||
{{if and (.Description.Integration) (ne .Description.Integration.ID "")}}_ = T("{{.Description.Integration.ID}}")
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
{{range .Categories}}
|
||||
var wtc{{.MD5}} = &WorkTemplateCategory{
|
||||
ID: "{{.ID}}",
|
||||
Name: "{{.Name}}",
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Templates}}
|
||||
var wt{{.MD5}} = &WorkTemplate{
|
||||
ID: "{{.ID}}",
|
||||
Category: "{{.Category}}",
|
||||
UseCase: "{{.UseCase}}",
|
||||
Illustration: "{{.Illustration}}",
|
||||
Visibility: "{{.Visibility}}",
|
||||
{{if .FeatureFlag}}FeatureFlag: &FeatureFlag{
|
||||
Name: "{{.FeatureFlag.Name}}",
|
||||
Value: "{{.FeatureFlag.Value}}",
|
||||
},{{end}}
|
||||
Description: Description{
|
||||
{{if .Description.Channel}}Channel: &TranslatableString{
|
||||
ID: "{{.Description.Channel.ID}}",
|
||||
DefaultMessage: "{{.Description.Channel.DefaultMessage}}",
|
||||
Illustration: "{{.Description.Channel.Illustration}}",
|
||||
},{{end}}
|
||||
{{if .Description.Board}}Board: &TranslatableString{
|
||||
ID: "{{.Description.Board.ID}}",
|
||||
DefaultMessage: "{{.Description.Board.DefaultMessage}}",
|
||||
Illustration: "{{.Description.Board.Illustration}}",
|
||||
},{{end}}
|
||||
{{if .Description.Playbook}}Playbook: &TranslatableString{
|
||||
ID: "{{.Description.Playbook.ID}}",
|
||||
DefaultMessage: "{{.Description.Playbook.DefaultMessage}}",
|
||||
Illustration: "{{.Description.Playbook.Illustration}}",
|
||||
},{{end}}
|
||||
{{if .Description.Integration}}Integration: &TranslatableString{
|
||||
ID: "{{.Description.Integration.ID}}",
|
||||
DefaultMessage: "{{.Description.Integration.DefaultMessage}}",
|
||||
Illustration: "{{.Description.Integration.Illustration}}",
|
||||
},{{end}}
|
||||
},
|
||||
Content: []Content{
|
||||
{{range .Content}}{
|
||||
{{if .Channel}}Channel: &Channel{
|
||||
ID: "{{.Channel.ID}}",
|
||||
Name: "{{.Channel.Name}}",
|
||||
Purpose: "{{.Channel.Purpose}}",
|
||||
Playbook: "{{.Channel.Playbook}}",
|
||||
Illustration: "{{.Channel.Illustration}}",
|
||||
},{{end}}{{if .Board}}Board: &Board{
|
||||
ID: "{{.Board.ID}}",
|
||||
Template: "{{.Board.Template}}",
|
||||
Name: "{{.Board.Name}}",
|
||||
Channel: "{{.Board.Channel}}",
|
||||
Illustration: "{{.Board.Illustration}}",
|
||||
},{{end}}{{if .Playbook}}Playbook: &Playbook{
|
||||
Template: "{{.Playbook.Template}}",
|
||||
Name: "{{.Playbook.Name}}",
|
||||
ID: "{{.Playbook.ID}}",
|
||||
Illustration: "{{.Playbook.Illustration}}",
|
||||
},{{end}}{{if .Integration}}Integration: &Integration{
|
||||
ID: "{{.Integration.ID}}",
|
||||
},{{end}}
|
||||
},
|
||||
{{end}}
|
||||
},
|
||||
}
|
||||
{{end}}
|
||||
106
server/channels/app/worktemplates/model.go
Обычный файл
106
server/channels/app/worktemplates/model.go
Обычный файл
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
package worktemplates
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
pbclient "github.com/mattermost/mattermost-plugin-playbooks/client"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
)
|
||||
|
||||
type ExecutionRequest struct {
|
||||
TeamID string `json:"team_id"`
|
||||
Name string `json:"name"`
|
||||
Visibility string `json:"visibility"`
|
||||
WorkTemplate model.WorkTemplate `json:"work_template"`
|
||||
PlaybookTemplates []*PlaybookTemplate `json:"playbook_templates"`
|
||||
|
||||
foundPlaybookTemplates map[string]*pbclient.PlaybookCreateOptions
|
||||
}
|
||||
|
||||
type PermissionSet struct {
|
||||
License *model.License
|
||||
|
||||
// channels
|
||||
CanCreatePublicChannel bool
|
||||
CanCreatePrivateChannel bool
|
||||
// playbooks
|
||||
CanCreatePublicPlaybook bool
|
||||
CanCreatePrivatePlaybook bool
|
||||
// boards
|
||||
CanCreatePublicBoard bool
|
||||
CanCreatePrivateBoard bool
|
||||
}
|
||||
|
||||
func (r *ExecutionRequest) CanBeExecuted(p PermissionSet) *model.AppError {
|
||||
public := r.Visibility == model.WorkTemplateVisibilityPublic
|
||||
for _, c := range r.WorkTemplate.Content {
|
||||
if c.Channel != nil {
|
||||
if public && !p.CanCreatePublicChannel {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.cannot_create_public_channel", nil, "", http.StatusForbidden)
|
||||
}
|
||||
if !public && !p.CanCreatePrivateChannel {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.cannot_create_private_channel", nil, "", http.StatusForbidden)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if c.Board != nil {
|
||||
if public && !p.CanCreatePublicBoard {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.cannot_create_public_board", nil, "", http.StatusForbidden)
|
||||
}
|
||||
if !public && !p.CanCreatePrivateBoard {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.cannot_create_private_board", nil, "", http.StatusForbidden)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if c.Playbook != nil {
|
||||
if public && !p.CanCreatePublicPlaybook {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.cannot_create_public_playbook", nil, "", http.StatusForbidden)
|
||||
}
|
||||
if !public && !p.CanCreatePrivatePlaybook {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.cannot_create_private_playbook", nil, "", http.StatusForbidden)
|
||||
}
|
||||
// private playbook is an E20/Enterprise feature
|
||||
if !public && (p.License == nil || (p.License.SkuShortName != model.LicenseShortSkuE20 && p.License.SkuShortName != model.LicenseShortSkuEnterprise)) {
|
||||
return model.NewAppError("WorkTemplateExecutionRequest.CanBeExecuted", "app.worktemplate.execution_request.license_cannot_create_private_playbook", nil, "", http.StatusForbidden)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindPlaybookTemplate returns the playbook template with the given title.
|
||||
// it also feed a cache to avoid looking for the same template twice.
|
||||
func (r *ExecutionRequest) FindPlaybookTemplate(templateTitle string) (*pbclient.PlaybookCreateOptions, error) {
|
||||
if r.foundPlaybookTemplates == nil {
|
||||
r.foundPlaybookTemplates = make(map[string]*pbclient.PlaybookCreateOptions)
|
||||
}
|
||||
|
||||
if pt, ok := r.foundPlaybookTemplates[templateTitle]; ok {
|
||||
if pt == nil {
|
||||
return nil, errors.New("playbook template not found")
|
||||
}
|
||||
return pt, nil
|
||||
}
|
||||
|
||||
for _, pt := range r.PlaybookTemplates {
|
||||
if pt.Title == templateTitle {
|
||||
r.foundPlaybookTemplates[templateTitle] = &pt.Template
|
||||
return &pt.Template, nil
|
||||
}
|
||||
}
|
||||
r.foundPlaybookTemplates[templateTitle] = nil
|
||||
return nil, errors.New("playbook template not found")
|
||||
}
|
||||
|
||||
type PlaybookTemplate struct {
|
||||
Title string `json:"title"`
|
||||
Template pbclient.PlaybookCreateOptions `json:"template"`
|
||||
}
|
||||
110
server/channels/app/worktemplates/model_test.go
Обычный файл
110
server/channels/app/worktemplates/model_test.go
Обычный файл
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
package worktemplates
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
|
||||
pbclient "github.com/mattermost/mattermost-plugin-playbooks/client"
|
||||
)
|
||||
|
||||
func TestCanBeExecuted(t *testing.T) {
|
||||
wtcr := &ExecutionRequest{
|
||||
Visibility: model.WorkTemplateVisibilityPublic,
|
||||
WorkTemplate: model.WorkTemplate{
|
||||
Content: []model.WorkTemplateContent{
|
||||
{
|
||||
Playbook: &model.WorkTemplatePlaybook{
|
||||
Name: "test playbook",
|
||||
ID: "test-pb",
|
||||
Template: "test template pb",
|
||||
},
|
||||
},
|
||||
{
|
||||
Channel: &model.WorkTemplateChannel{
|
||||
ID: "test-channel",
|
||||
Name: "test channel",
|
||||
Playbook: "test-pb",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &model.WorkTemplateBoard{
|
||||
Name: "test board",
|
||||
Channel: "test-channel",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
PlaybookTemplates: []*PlaybookTemplate{
|
||||
{
|
||||
Title: "test template pb",
|
||||
Template: pbclient.PlaybookCreateOptions{
|
||||
CreatePublicPlaybookRun: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("can run when all permissions are good", func(t *testing.T) {
|
||||
appErr := wtcr.CanBeExecuted(PermissionSet{
|
||||
CanCreatePublicChannel: true,
|
||||
CanCreatePublicPlaybook: true,
|
||||
CanCreatePublicBoard: true,
|
||||
})
|
||||
assert.Nil(t, appErr)
|
||||
})
|
||||
|
||||
t.Run("cannot create private playbook if the license is not enterprise", func(t *testing.T) {
|
||||
wtcrMod := *wtcr
|
||||
wtcrMod.Visibility = model.WorkTemplateVisibilityPrivate
|
||||
appErr := wtcrMod.CanBeExecuted(PermissionSet{
|
||||
License: model.NewTestLicenseSKU(model.LicenseShortSkuProfessional, ""),
|
||||
CanCreatePrivateChannel: true,
|
||||
CanCreatePrivateBoard: true,
|
||||
CanCreatePrivatePlaybook: true,
|
||||
CanCreatePublicChannel: true, // needed for the channel run
|
||||
})
|
||||
require.NotNil(t, appErr)
|
||||
|
||||
appErr = wtcrMod.CanBeExecuted(PermissionSet{
|
||||
License: nil,
|
||||
CanCreatePrivateChannel: true,
|
||||
CanCreatePrivateBoard: true,
|
||||
CanCreatePrivatePlaybook: true,
|
||||
CanCreatePublicChannel: true,
|
||||
})
|
||||
require.NotNil(t, appErr)
|
||||
|
||||
// enterprise and E20 ok
|
||||
appErr = wtcrMod.CanBeExecuted(PermissionSet{
|
||||
License: model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, ""),
|
||||
CanCreatePrivateChannel: true,
|
||||
CanCreatePrivateBoard: true,
|
||||
CanCreatePrivatePlaybook: true,
|
||||
CanCreatePublicChannel: true,
|
||||
})
|
||||
require.Nil(t, appErr)
|
||||
appErr = wtcrMod.CanBeExecuted(PermissionSet{
|
||||
License: model.NewTestLicenseSKU(model.LicenseShortSkuE20, ""),
|
||||
CanCreatePrivateChannel: true,
|
||||
CanCreatePrivateBoard: true,
|
||||
CanCreatePrivatePlaybook: true,
|
||||
CanCreatePublicChannel: true,
|
||||
})
|
||||
require.Nil(t, appErr)
|
||||
})
|
||||
|
||||
t.Run("fails when something is not allowed", func(t *testing.T) {
|
||||
appErr := wtcr.CanBeExecuted(PermissionSet{
|
||||
CanCreatePublicChannel: true,
|
||||
CanCreatePublicPlaybook: false,
|
||||
CanCreatePublicBoard: true,
|
||||
})
|
||||
require.NotNil(t, appErr)
|
||||
})
|
||||
}
|
||||
397
server/channels/app/worktemplates/templates.yaml
Обычный файл
397
server/channels/app/worktemplates/templates.yaml
Обычный файл
@@ -0,0 +1,397 @@
|
||||
######################
|
||||
# PRODUCT TEAMS
|
||||
######################
|
||||
id: "product_teams/feature_release:v1"
|
||||
category: product_teams
|
||||
useCase: Manage feature release
|
||||
illustration: /static/worktemplates/product_teams/feature_release/feature_release.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: "worktemplate.product_teams.feature_release.description.channel"
|
||||
defaultMessage: "Chat with your team in a Feature Release channel that connects easily with your boards, playbooks and app bots."
|
||||
board:
|
||||
id: "worktemplate.product_teams.feature_release.description.board"
|
||||
defaultMessage: "Use our Meeting Agenda board template for recurring meetings like standup and our Project Tasks board to manage the progress of tasks along the way."
|
||||
playbook:
|
||||
id: "worktemplate.product_teams.feature_release.description.playbook"
|
||||
defaultMessage: "Create transparent workflows across development teams to ensure your feature development process is seamless."
|
||||
integration:
|
||||
id: "worktemplate.product_teams.feature_release.description.integration"
|
||||
defaultMessage: "Increase productivity in your channel by integrating a Jira bot and Github bot. These will be downloaded for you."
|
||||
illustration: "/static/worktemplates/integrations.png"
|
||||
content:
|
||||
- channel:
|
||||
id: feature-release
|
||||
name: Feature Release
|
||||
playbook: product-release-playbook
|
||||
illustration: "/static/worktemplates/product_teams/feature_release/channel.png"
|
||||
- board:
|
||||
id: "board-meeting-agenda"
|
||||
template: "54fcf9c610f0ac5e4c522c0657c90602"
|
||||
name: Meeting Agenda
|
||||
channel: feature-release
|
||||
illustration: "/static/worktemplates/boards/meeting_agenda.png"
|
||||
- board:
|
||||
id: "board-project-task"
|
||||
template: "a4ec399ab4f2088b1051c3cdf1dde4c3"
|
||||
name: Project Task
|
||||
channel: feature-release
|
||||
illustration: "/static/worktemplates/boards/project_tasks.png"
|
||||
- playbook:
|
||||
template: "Product Release"
|
||||
name: "Feature release"
|
||||
id: product-release-playbook
|
||||
illustration: "/static/worktemplates/playbooks/product_release.png"
|
||||
- integration:
|
||||
id: jira
|
||||
- integration:
|
||||
id: github
|
||||
---
|
||||
id: 'product_teams/goals_and_okrs:v1'
|
||||
category: product_teams
|
||||
useCase: Set goals and OKR's
|
||||
illustration: /static/worktemplates/product_teams/goals_and_okrs/goals_and_okrs.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.product_teams.goals_and_okrs.channel
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
board:
|
||||
id: worktemplate.product_teams.goals_and_okrs.board
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
integration:
|
||||
id: worktemplate.product_teams.goals_and_okrs.integration
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
illustration: /static/worktemplates/integrations.png
|
||||
content:
|
||||
- channel:
|
||||
id: channel-1674845108569
|
||||
illustration: /static/worktemplates/product_teams/goals_and_okrs/channel.png
|
||||
name: Goals and OKR
|
||||
- board:
|
||||
id: board-1674845139258
|
||||
template: 7ba22ccfdfac391d63dea5c4b8cde0de
|
||||
name: Goals and OKR
|
||||
illustration: /static/worktemplates/boards/company_goal_and_okrs.png
|
||||
channel: channel-1674845108569
|
||||
- board:
|
||||
id: board-1674845175528
|
||||
template: 54fcf9c610f0ac5e4c522c0657c90602
|
||||
name: Meeting Agenda
|
||||
illustration: /static/worktemplates/boards/meeting_agenda.png
|
||||
channel: channel-1674845108569
|
||||
- integration:
|
||||
id: zoom
|
||||
|
||||
---
|
||||
id: 'product_teams/bug_bash:v1'
|
||||
category: product_teams
|
||||
useCase: Run a bug bash
|
||||
illustration: /static/worktemplates/product_teams/bug_bash/bug_bash.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.product_teams.bug_bash.channel
|
||||
defaultMessage: >-
|
||||
Get organized and bash all the bugs with this project! Build momentum and
|
||||
measure progress using included Playbook, Board, and Channel.
|
||||
board:
|
||||
id: worktemplate.product_teams.bug_bash.board
|
||||
defaultMessage: >-
|
||||
Get organized and bash all the bugs with this project! Build momentum and
|
||||
measure progress using included Playbook, Board, and Channel.
|
||||
playbook:
|
||||
id: worktemplate.product_teams.bug_bash.playbook
|
||||
defaultMessage: >-
|
||||
Get organized and bash all the bugs with this project! Build momentum and
|
||||
measure progress using included Playbook, Board, and Channel.
|
||||
integration:
|
||||
id: worktemplate.product_teams.bug_bash.integration
|
||||
defaultMessage: >-
|
||||
Get organized and bash all the bugs with this project! Build momentum and
|
||||
measure progress using included Playbook, Board, and Channel.
|
||||
illustration: /static/worktemplates/integrations.png
|
||||
content:
|
||||
- playbook:
|
||||
id: playbook-1674844017943
|
||||
template: Bug Bash
|
||||
name: Bug Bash
|
||||
illustration: /static/worktemplates/playbooks/bug_bash.png
|
||||
- channel:
|
||||
id: channel-1674844017943
|
||||
illustration: /static/worktemplates/product_teams/bug_bash/channel.png
|
||||
name: Bug Bash
|
||||
playbook: playbook-1674844017943
|
||||
- integration:
|
||||
id: jira
|
||||
---
|
||||
id: 'product_teams/sprint_planning:v1'
|
||||
category: product_teams
|
||||
useCase: Plan sprints
|
||||
illustration: /static/worktemplates/product_teams/sprint_planning/sprint_planning.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.product_teams.sprint_planning.channel
|
||||
defaultMessage: >-
|
||||
Use a Project to make sprint planning a breeze. The channel keeps the
|
||||
conversation and questions focused. The sprint plan keeps everyone on task
|
||||
for the week and the Retrospective board brings the team together to
|
||||
continuously improve.
|
||||
board:
|
||||
id: worktemplate.product_teams.sprint_planning.board
|
||||
defaultMessage: >-
|
||||
Use a Project to make sprint planning a breeze. The channel keeps the
|
||||
conversation and questions focused. The sprint plan keeps everyone on task
|
||||
for the week and the Retrospective board brings the team together to
|
||||
continuously improve.
|
||||
integration:
|
||||
id: worktemplate.product_teams.sprint_planning.integration
|
||||
defaultMessage: >-
|
||||
Use a Project to make sprint planning a breeze. The channel keeps the
|
||||
conversation and questions focused. The sprint plan keeps everyone on task
|
||||
for the week and the Retrospective board brings the team together to
|
||||
continuously improve.
|
||||
illustration: /static/worktemplates/integrations.png
|
||||
content:
|
||||
- channel:
|
||||
id: channel-1674850783500
|
||||
illustration: /static/worktemplates/product_teams/sprint_planning/channel.png
|
||||
name: Sprint planning
|
||||
- board:
|
||||
id: board-1674850783973
|
||||
template: 99b74e26d2f5d0a9b346d43c0a7bfb09
|
||||
name: Sprint planning
|
||||
illustration: /static/worktemplates/boards/sprint_planner.png
|
||||
channel: channel-1674850783500
|
||||
- integration:
|
||||
id: zoom
|
||||
---
|
||||
id: 'product_teams/product_roadmap:v1'
|
||||
category: product_teams
|
||||
useCase: Create a product roadmap
|
||||
illustration: /static/worktemplates/product_teams/product_roadmap/product_roadmap.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.product_teams.product_roadmap.channel
|
||||
defaultMessage: Description of why the channel(s) are needed
|
||||
board:
|
||||
id: worktemplate.product_teams.product_roadmap.board
|
||||
defaultMessage: Description of why the board(s) are needed
|
||||
content:
|
||||
- channel:
|
||||
id: channel-1674851139450
|
||||
illustration: /static/worktemplates/product_teams/product_roadmap/channel.png
|
||||
name: Product Roadmap
|
||||
- board:
|
||||
id: board-1674851139759
|
||||
template: b728c6ca730e2cfc229741c5a4712b65
|
||||
name: Product Roadmap
|
||||
illustration: /static/worktemplates/boards/roadmap.png
|
||||
channel: channel-1674851139450
|
||||
---
|
||||
######################
|
||||
# DEVOPS
|
||||
######################
|
||||
id: 'devops/incident_resolution:v1'
|
||||
category: devops
|
||||
useCase: Resolve incidents
|
||||
illustration: /static/worktemplates/devops/incident_resolution/incident_resolution.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: "worktemplate.devops.incident_resolution.description.channel"
|
||||
defaultMessage: "When everything is going wrong, having a repeatable process is the key to making sure everything is made right as quickly as possible. This Project combines everything Mattermost offers to ensure the fires are put out and stakeholders informed along the way."
|
||||
board:
|
||||
id: "worktemplate.devops.incident_resolution.description.board"
|
||||
defaultMessage: "When everything is going wrong, having a repeatable process is the key to making sure everything is made right as quickly as possible. This Project combines everything Mattermost offers to ensure the fires are put out and stakeholders informed along the way."
|
||||
playbook:
|
||||
id: "worktemplate.devops.incident_resolution.description.playbook"
|
||||
defaultMessage: "When everything is going wrong, having a repeatable process is the key to making sure everything is made right as quickly as possible. This Project combines everything Mattermost offers to ensure the fires are put out and stakeholders informed along the way."
|
||||
content:
|
||||
- playbook:
|
||||
id: irpb
|
||||
template: Incident Resolution
|
||||
name: Incident Resolution
|
||||
illustration: /static/worktemplates/playbooks/incident_resolution.png
|
||||
- channel:
|
||||
id: irc
|
||||
illustration: /static/worktemplates/devops/incident_resolution/channel.png
|
||||
name: Incident Resolution
|
||||
playbook: irpb
|
||||
- board:
|
||||
id: irb
|
||||
template: a4ec399ab4f2088b1051c3cdf1dde4c3
|
||||
name: Incident Resolution
|
||||
illustration: /static/worktemplates/boards/project_tasks.png
|
||||
channel: irc
|
||||
---
|
||||
id: 'devops/product_release:v1'
|
||||
category: devops
|
||||
useCase: Prepare a product release
|
||||
illustration: /static/worktemplates/devops/product_release/product_release.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.devops.product_release.channel
|
||||
defaultMessage: Don’t miss a step during a product release with this Project. Assign tasks from the Playbook checklist and hit milestones with the Board. Use Channels to keep everyone on the same page.
|
||||
board:
|
||||
id: worktemplate.devops.product_release.board
|
||||
defaultMessage: Don’t miss a step during a product release with this Project. Assign tasks from the Playbook checklist and hit milestones with the Board. Use Channels to keep everyone on the same page.
|
||||
playbook:
|
||||
id: worktemplate.devops.product_release.playbook
|
||||
defaultMessage: Don’t miss a step during a product release with this Project. Assign tasks from the Playbook checklist and hit milestones with the Board. Use Channels to keep everyone on the same page.
|
||||
content:
|
||||
- playbook:
|
||||
id: playbook-1674851385983
|
||||
template: Product Release
|
||||
name: Product Release
|
||||
illustration: /static/worktemplates/playbooks/product_release.png
|
||||
- channel:
|
||||
id: channel-1674851385983
|
||||
illustration: /static/worktemplates/devops/product_release/channel.png
|
||||
name: Product Release
|
||||
playbook: playbook-1674851385983
|
||||
- board:
|
||||
id: board-1674851386432
|
||||
template: a4ec399ab4f2088b1051c3cdf1dde4c3
|
||||
name: Product Release
|
||||
illustration: /static/worktemplates/boards/project_tasks.png
|
||||
channel: channel-1674851385983
|
||||
---
|
||||
######################
|
||||
# COMPANY WIDE
|
||||
######################
|
||||
id: 'companywide/goals_and_okrs:v1'
|
||||
category: companywide
|
||||
useCase: Set goals and OKR's
|
||||
illustration: /static/worktemplates/companywide/goals_and_okrs/goals_and_okrs.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.companywide.goals_and_okrs.channel
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
board:
|
||||
id: worktemplate.companywide.goals_and_okrs.board
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
integration:
|
||||
id: worktemplate.companywide.goals_and_okrs.integration
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
illustration: /static/worktemplates/integrations.png
|
||||
content:
|
||||
- channel:
|
||||
id: channel-1674845108569
|
||||
illustration: /static/worktemplates/companywide/goals_and_okrs/channel.png
|
||||
name: Goals and OKR
|
||||
- board:
|
||||
id: board-1674845139258
|
||||
template: 7ba22ccfdfac391d63dea5c4b8cde0de
|
||||
name: Goals and OKR
|
||||
illustration: /static/worktemplates/boards/company_goal_and_okrs.png
|
||||
channel: channel-1674845108569
|
||||
- integration:
|
||||
id: zoom
|
||||
---
|
||||
id: 'companywide/create_project:v1'
|
||||
category: companywide
|
||||
useCase: Create a project
|
||||
illustration: /static/worktemplates/companywide/create_project/create_project.svg
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.companywide.create_project.channel
|
||||
defaultMessage: >-
|
||||
Plan a Roadmap using this Project Board and collaborate on topic in the
|
||||
channel created with this template.
|
||||
board:
|
||||
id: worktemplate.companywide.create_project.board
|
||||
defaultMessage: >-
|
||||
Plan a Roadmap using this Project Board and collaborate on topic in the
|
||||
channel created with this template.
|
||||
integration:
|
||||
id: worktemplate.companywide.create_project.integration
|
||||
defaultMessage: >-
|
||||
Plan a Roadmap using this Project Board and collaborate on topic in the
|
||||
channel created with this template.
|
||||
illustration: /static/worktemplates/integrations.png
|
||||
content:
|
||||
- channel:
|
||||
id: channel-1674851940114
|
||||
illustration: >-
|
||||
/static/worktemplates/companywide/create_project/channel.png
|
||||
name: Create Project
|
||||
- board:
|
||||
id: board-1674851940548
|
||||
template: a4ec399ab4f2088b1051c3cdf1dde4c3
|
||||
name: Create Project
|
||||
illustration: /static/worktemplates/boards/project_tasks.png
|
||||
channel: channel-1674851940114
|
||||
- integration:
|
||||
id: jira
|
||||
- integration:
|
||||
id: github
|
||||
- integration:
|
||||
id: zoom
|
||||
---
|
||||
######################
|
||||
# Leadership
|
||||
######################
|
||||
id: 'leadership/goals_and_okrs:v1'
|
||||
category: leadership
|
||||
useCase: Set goals and OKR's
|
||||
illustration: /static/worktemplates/leadership/goals_and_okrs/goals_and_okrs.png
|
||||
visibility: public
|
||||
description:
|
||||
channel:
|
||||
id: worktemplate.leadership.goals_and_okrs.channel
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
board:
|
||||
id: worktemplate.leadership.goals_and_okrs.board
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
integration:
|
||||
id: worktemplate.leadership.goals_and_okrs.integration
|
||||
defaultMessage: >-
|
||||
Clear focus is essential to team success and with this Project you can
|
||||
document the team’s goals and OKR’s as well as post updates in the
|
||||
dedicated channel.
|
||||
illustration: /static/worktemplates/integrations.png
|
||||
content:
|
||||
- channel:
|
||||
id: channel-1674845108569
|
||||
illustration: /static/worktemplates/leadership/goals_and_okrs/channel.png
|
||||
name: Goals and OKR
|
||||
- board:
|
||||
id: board-1674845139258
|
||||
template: 7ba22ccfdfac391d63dea5c4b8cde0de
|
||||
name: Goals and OKR
|
||||
illustration: /static/worktemplates/boards/company_goal_and_okrs.png
|
||||
channel: channel-1674845108569
|
||||
- integration:
|
||||
id: zoom
|
||||
|
||||
343
server/channels/app/worktemplates/types.go
Обычный файл
343
server/channels/app/worktemplates/types.go
Обычный файл
@@ -0,0 +1,343 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package worktemplates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/server/platform/shared/i18n"
|
||||
)
|
||||
|
||||
type WorkTemplateCategory struct {
|
||||
ID string `yaml:"id"`
|
||||
Name string `yaml:"name"`
|
||||
}
|
||||
|
||||
type WorkTemplate struct {
|
||||
ID string `yaml:"id"`
|
||||
Category string `yaml:"category"`
|
||||
UseCase string `yaml:"useCase"`
|
||||
Illustration string `yaml:"illustration"`
|
||||
Visibility string `yaml:"visibility"`
|
||||
FeatureFlag *FeatureFlag `yaml:"featureFlag,omitempty"`
|
||||
Description Description `yaml:"description"`
|
||||
Content []Content `yaml:"content"`
|
||||
}
|
||||
|
||||
func (wt WorkTemplate) ToModelWorkTemplate(t i18n.TranslateFunc) *model.WorkTemplate {
|
||||
mwt := &model.WorkTemplate{
|
||||
ID: wt.ID,
|
||||
Category: wt.Category,
|
||||
UseCase: wt.UseCase,
|
||||
Illustration: wt.Illustration,
|
||||
Visibility: wt.Visibility,
|
||||
}
|
||||
|
||||
if wt.FeatureFlag != nil {
|
||||
mwt.FeatureFlag = &model.WorkTemplateFeatureFlag{
|
||||
Name: wt.FeatureFlag.Name,
|
||||
Value: wt.FeatureFlag.Value,
|
||||
}
|
||||
}
|
||||
|
||||
if wt.Description.Channel != nil {
|
||||
mwt.Description.Channel = &model.DescriptionContent{
|
||||
Message: wt.Description.Channel.Translate(t),
|
||||
Illustration: wt.Description.Channel.Illustration,
|
||||
}
|
||||
}
|
||||
|
||||
if wt.Description.Board != nil {
|
||||
mwt.Description.Board = &model.DescriptionContent{
|
||||
Message: wt.Description.Board.Translate(t),
|
||||
Illustration: wt.Description.Board.Illustration,
|
||||
}
|
||||
}
|
||||
|
||||
if wt.Description.Playbook != nil {
|
||||
mwt.Description.Playbook = &model.DescriptionContent{
|
||||
Message: wt.Description.Playbook.Translate(t),
|
||||
Illustration: wt.Description.Playbook.Illustration,
|
||||
}
|
||||
}
|
||||
|
||||
if wt.Description.Integration != nil {
|
||||
mwt.Description.Integration = &model.DescriptionContent{
|
||||
Message: wt.Description.Integration.Translate(t),
|
||||
Illustration: wt.Description.Integration.Illustration,
|
||||
}
|
||||
}
|
||||
|
||||
for _, content := range wt.Content {
|
||||
if content.Channel != nil {
|
||||
mwt.Content = append(mwt.Content, model.WorkTemplateContent{
|
||||
Channel: &model.WorkTemplateChannel{
|
||||
ID: content.Channel.ID,
|
||||
Name: content.Channel.Name,
|
||||
Purpose: content.Channel.Purpose,
|
||||
Playbook: content.Channel.Playbook,
|
||||
Illustration: content.Channel.Illustration,
|
||||
},
|
||||
})
|
||||
}
|
||||
if content.Board != nil {
|
||||
mwt.Content = append(mwt.Content, model.WorkTemplateContent{
|
||||
Board: &model.WorkTemplateBoard{
|
||||
ID: content.Board.ID,
|
||||
Name: content.Board.Name,
|
||||
Template: content.Board.Template,
|
||||
Channel: content.Board.Channel,
|
||||
Illustration: content.Board.Illustration,
|
||||
},
|
||||
})
|
||||
}
|
||||
if content.Playbook != nil {
|
||||
mwt.Content = append(mwt.Content, model.WorkTemplateContent{
|
||||
Playbook: &model.WorkTemplatePlaybook{
|
||||
ID: content.Playbook.ID,
|
||||
Name: content.Playbook.Name,
|
||||
Template: content.Playbook.Template,
|
||||
Illustration: content.Playbook.Illustration,
|
||||
},
|
||||
})
|
||||
}
|
||||
if content.Integration != nil {
|
||||
mwt.Content = append(mwt.Content, model.WorkTemplateContent{
|
||||
Integration: &model.WorkTemplateIntegration{
|
||||
ID: content.Integration.ID,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return mwt
|
||||
}
|
||||
|
||||
func (wt WorkTemplate) Validate(categoryIds map[string]struct{}) error {
|
||||
if wt.ID == "" {
|
||||
return errors.New("id is required")
|
||||
}
|
||||
if wt.Category == "" {
|
||||
return errors.New("category is required")
|
||||
}
|
||||
if _, ok := categoryIds[wt.Category]; !ok {
|
||||
return fmt.Errorf("category %s does not exist", wt.Category)
|
||||
}
|
||||
if wt.UseCase == "" {
|
||||
return errors.New("useCase is required")
|
||||
}
|
||||
if wt.Illustration == "" {
|
||||
return errors.New("illustration is required")
|
||||
}
|
||||
if wt.Visibility == "" {
|
||||
return errors.New("visibility is required")
|
||||
}
|
||||
hasChannel := false
|
||||
hasBoard := false
|
||||
hasPlaybook := false
|
||||
hasIntegration := false
|
||||
foundChannels := map[string]struct{}{}
|
||||
foundPlaybooks := map[string]struct{}{}
|
||||
foundBoards := map[string]struct{}{}
|
||||
foundIntegrations := map[string]struct{}{}
|
||||
mustHaveChannels := []string{}
|
||||
mustHavePlaybooks := []string{}
|
||||
|
||||
currentIdx := 0
|
||||
for _, content := range wt.Content {
|
||||
if content.Channel != nil {
|
||||
hasChannel = true
|
||||
if cErr := content.Channel.Validate(); cErr != nil {
|
||||
return wrapContentError(cErr, currentIdx)
|
||||
}
|
||||
if _, ok := foundChannels[content.Channel.ID]; ok {
|
||||
return wrapContentError(fmt.Errorf("duplicate channel %s found", content.Channel.ID), currentIdx)
|
||||
}
|
||||
foundChannels[content.Channel.ID] = struct{}{}
|
||||
|
||||
if content.Channel.Playbook != "" {
|
||||
mustHavePlaybooks = append(mustHavePlaybooks, content.Channel.Playbook)
|
||||
}
|
||||
}
|
||||
|
||||
if content.Board != nil {
|
||||
hasBoard = true
|
||||
if cErr := content.Board.Validate(); cErr != nil {
|
||||
return wrapContentError(cErr, currentIdx)
|
||||
}
|
||||
if _, ok := foundBoards[content.Board.ID]; ok {
|
||||
return wrapContentError(fmt.Errorf("duplicate board %s found", content.Board.ID), currentIdx)
|
||||
}
|
||||
foundBoards[content.Board.ID] = struct{}{}
|
||||
|
||||
if content.Board.Channel != "" {
|
||||
mustHaveChannels = append(mustHaveChannels, content.Board.Channel)
|
||||
}
|
||||
}
|
||||
if content.Playbook != nil {
|
||||
hasPlaybook = true
|
||||
if cErr := content.Playbook.Validate(); cErr != nil {
|
||||
return wrapContentError(cErr, currentIdx)
|
||||
}
|
||||
if _, ok := foundPlaybooks[content.Playbook.ID]; ok {
|
||||
return wrapContentError(fmt.Errorf("duplicate playbook %s found", content.Playbook.ID), currentIdx)
|
||||
}
|
||||
foundPlaybooks[content.Playbook.ID] = struct{}{}
|
||||
}
|
||||
if content.Integration != nil {
|
||||
hasIntegration = true
|
||||
if cErr := content.Integration.Validate(); cErr != nil {
|
||||
return wrapContentError(cErr, currentIdx)
|
||||
}
|
||||
if _, ok := foundIntegrations[content.Integration.ID]; ok {
|
||||
return wrapContentError(fmt.Errorf("duplicate integration %s found", content.Integration.ID), currentIdx)
|
||||
}
|
||||
foundIntegrations[content.Integration.ID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
if hasChannel && wt.Description.Channel == nil {
|
||||
return errors.New("description.channel is required")
|
||||
}
|
||||
if hasBoard && wt.Description.Board == nil {
|
||||
return errors.New("description.board is required")
|
||||
}
|
||||
if hasPlaybook && wt.Description.Playbook == nil {
|
||||
return errors.New("description.playbook is required")
|
||||
}
|
||||
if hasIntegration && wt.Description.Integration == nil {
|
||||
return errors.New("description.integration is required")
|
||||
}
|
||||
|
||||
for _, channel := range mustHaveChannels {
|
||||
if _, ok := foundChannels[channel]; !ok {
|
||||
return fmt.Errorf("channel %s is required", channel)
|
||||
}
|
||||
}
|
||||
|
||||
for _, playbook := range mustHavePlaybooks {
|
||||
if _, ok := foundPlaybooks[playbook]; !ok {
|
||||
return fmt.Errorf("playbook %s is required", playbook)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type FeatureFlag struct {
|
||||
Name string `yaml:"name"`
|
||||
Value string `yaml:"value"`
|
||||
}
|
||||
|
||||
type TranslatableString struct {
|
||||
ID string `yaml:"id"`
|
||||
DefaultMessage string `yaml:"defaultMessage"`
|
||||
Illustration string `yaml:"illustration"`
|
||||
}
|
||||
|
||||
func (ts TranslatableString) Translate(t i18n.TranslateFunc) string {
|
||||
if ts.ID != "" {
|
||||
msg := t(ts.ID)
|
||||
if msg != ts.ID && msg != "" {
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
return ts.DefaultMessage
|
||||
}
|
||||
|
||||
type Description struct {
|
||||
Channel *TranslatableString `yaml:"channel"`
|
||||
Board *TranslatableString `yaml:"board"`
|
||||
Playbook *TranslatableString `yaml:"playbook"`
|
||||
Integration *TranslatableString `yaml:"integration"`
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
ID string `yaml:"id"`
|
||||
Name string `yaml:"name"`
|
||||
Purpose string `yaml:"purpose"`
|
||||
Playbook string `yaml:"playbook"`
|
||||
Illustration string `yaml:"illustration"`
|
||||
}
|
||||
|
||||
func (c *Channel) Validate() error {
|
||||
if c.ID == "" {
|
||||
return errors.New("id is required")
|
||||
}
|
||||
if c.Name == "" {
|
||||
return errors.New("name is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Board struct {
|
||||
ID string `yaml:"id"`
|
||||
Template string `yaml:"template"`
|
||||
Name string `yaml:"name"`
|
||||
Channel string `yaml:"channel"`
|
||||
Illustration string `yaml:"illustration"`
|
||||
}
|
||||
|
||||
func (b Board) Validate() error {
|
||||
if b.ID == "" {
|
||||
return errors.New("id is required")
|
||||
}
|
||||
if b.Template == "" {
|
||||
return errors.New("template is required")
|
||||
}
|
||||
if b.Name == "" {
|
||||
return errors.New("name is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Playbook struct {
|
||||
Template string `yaml:"template"`
|
||||
Name string `yaml:"name"`
|
||||
ID string `yaml:"id"`
|
||||
Illustration string `yaml:"illustration"`
|
||||
}
|
||||
|
||||
func (p *Playbook) Validate() error {
|
||||
if p.ID == "" {
|
||||
return errors.New("id is required")
|
||||
}
|
||||
if p.Template == "" {
|
||||
return errors.New("template is required")
|
||||
}
|
||||
if p.Name == "" {
|
||||
return errors.New("name is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Integration struct {
|
||||
ID string `yaml:"id"`
|
||||
}
|
||||
|
||||
func (i *Integration) Validate() error {
|
||||
if i.ID == "" {
|
||||
return errors.New("id is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
Channel *Channel `yaml:"channel,omitempty"`
|
||||
Board *Board `yaml:"board,omitempty"`
|
||||
Playbook *Playbook `yaml:"playbook,omitempty"`
|
||||
Integration *Integration `yaml:"integration,omitempty"`
|
||||
}
|
||||
|
||||
func wrapContentError(err error, index int) error {
|
||||
return errors.Wrapf(err, "content #%d validation failed", index)
|
||||
}
|
||||
644
server/channels/app/worktemplates/worktemplate_generated.go
Обычный файл
644
server/channels/app/worktemplates/worktemplate_generated.go
Обычный файл
@@ -0,0 +1,644 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Code generated by "make generate-worktemplates"
|
||||
// DO NOT EDIT
|
||||
|
||||
package worktemplates
|
||||
|
||||
func init() {
|
||||
registerWorkTemplateCategory("product_teams", wtc846b565cd80043537945134a54812e07)
|
||||
registerWorkTemplateCategory("devops", wtca21c218df41f6d7fd032535fe20394e2)
|
||||
registerWorkTemplateCategory("companywide", wtca6def90c2edac0c33650ac8ebee1e094)
|
||||
registerWorkTemplateCategory("leadership", wtce9b74766edff1096ba7c67999ca259b6)
|
||||
registerWorkTemplate("product_teams/feature_release:v1", wt00a1b44a5831c0a3acb14787b3fdd352)
|
||||
registerWorkTemplate("product_teams/goals_and_okrs:v1", wt5baa68055bf9ea423273662e01ccc575)
|
||||
registerWorkTemplate("product_teams/bug_bash:v1", wtfeb56bc6a8f277c47b503bd1c92d830e)
|
||||
registerWorkTemplate("product_teams/sprint_planning:v1", wt8d2ef53deac5517eb349dc5de6150196)
|
||||
registerWorkTemplate("product_teams/product_roadmap:v1", wt00ab91a945627f4a624957dd80490bb2)
|
||||
registerWorkTemplate("devops/incident_resolution:v1", wtce19b9352a59d6a5d26f292d83e84377)
|
||||
registerWorkTemplate("devops/product_release:v1", wt37406285a41c18bcdeb881189f7acde0)
|
||||
registerWorkTemplate("companywide/goals_and_okrs:v1", wtf7b846d35810f8272eeb9a1a562025b5)
|
||||
registerWorkTemplate("companywide/create_project:v1", wtb9ab412890c2410c7b49eec8f12e7edc)
|
||||
registerWorkTemplate("leadership/goals_and_okrs:v1", wt32ab773bfe021e3d4913931041552559)
|
||||
|
||||
// Register categories strings
|
||||
_ = T("worktemplate.category.product_teams")
|
||||
_ = T("worktemplate.category.devops")
|
||||
_ = T("worktemplate.category.companywide")
|
||||
_ = T("worktemplate.category.leadership")
|
||||
|
||||
// Register translation strings
|
||||
_ = T("worktemplate.product_teams.feature_release.description.channel")
|
||||
_ = T("worktemplate.product_teams.feature_release.description.board")
|
||||
_ = T("worktemplate.product_teams.feature_release.description.playbook")
|
||||
_ = T("worktemplate.product_teams.feature_release.description.integration")
|
||||
_ = T("worktemplate.product_teams.goals_and_okrs.channel")
|
||||
_ = T("worktemplate.product_teams.goals_and_okrs.board")
|
||||
_ = T("worktemplate.product_teams.goals_and_okrs.integration")
|
||||
_ = T("worktemplate.product_teams.bug_bash.channel")
|
||||
_ = T("worktemplate.product_teams.bug_bash.board")
|
||||
_ = T("worktemplate.product_teams.bug_bash.playbook")
|
||||
_ = T("worktemplate.product_teams.bug_bash.integration")
|
||||
_ = T("worktemplate.product_teams.sprint_planning.channel")
|
||||
_ = T("worktemplate.product_teams.sprint_planning.board")
|
||||
_ = T("worktemplate.product_teams.sprint_planning.integration")
|
||||
_ = T("worktemplate.product_teams.product_roadmap.channel")
|
||||
_ = T("worktemplate.product_teams.product_roadmap.board")
|
||||
_ = T("worktemplate.devops.incident_resolution.description.channel")
|
||||
_ = T("worktemplate.devops.incident_resolution.description.board")
|
||||
_ = T("worktemplate.devops.incident_resolution.description.playbook")
|
||||
_ = T("worktemplate.devops.product_release.channel")
|
||||
_ = T("worktemplate.devops.product_release.board")
|
||||
_ = T("worktemplate.devops.product_release.playbook")
|
||||
_ = T("worktemplate.companywide.goals_and_okrs.channel")
|
||||
_ = T("worktemplate.companywide.goals_and_okrs.board")
|
||||
_ = T("worktemplate.companywide.goals_and_okrs.integration")
|
||||
_ = T("worktemplate.companywide.create_project.channel")
|
||||
_ = T("worktemplate.companywide.create_project.board")
|
||||
_ = T("worktemplate.companywide.create_project.integration")
|
||||
_ = T("worktemplate.leadership.goals_and_okrs.channel")
|
||||
_ = T("worktemplate.leadership.goals_and_okrs.board")
|
||||
_ = T("worktemplate.leadership.goals_and_okrs.integration")
|
||||
}
|
||||
|
||||
var wtc846b565cd80043537945134a54812e07 = &WorkTemplateCategory{
|
||||
ID: "product_teams",
|
||||
Name: "worktemplate.category.product_teams",
|
||||
}
|
||||
|
||||
var wtca21c218df41f6d7fd032535fe20394e2 = &WorkTemplateCategory{
|
||||
ID: "devops",
|
||||
Name: "worktemplate.category.devops",
|
||||
}
|
||||
|
||||
var wtca6def90c2edac0c33650ac8ebee1e094 = &WorkTemplateCategory{
|
||||
ID: "companywide",
|
||||
Name: "worktemplate.category.companywide",
|
||||
}
|
||||
|
||||
var wtce9b74766edff1096ba7c67999ca259b6 = &WorkTemplateCategory{
|
||||
ID: "leadership",
|
||||
Name: "worktemplate.category.leadership",
|
||||
}
|
||||
|
||||
var wt00a1b44a5831c0a3acb14787b3fdd352 = &WorkTemplate{
|
||||
ID: "product_teams/feature_release:v1",
|
||||
Category: "product_teams",
|
||||
UseCase: "Manage feature release",
|
||||
Illustration: "/static/worktemplates/product_teams/feature_release/feature_release.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.feature_release.description.channel",
|
||||
DefaultMessage: "Chat with your team in a Feature Release channel that connects easily with your boards, playbooks and app bots.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.feature_release.description.board",
|
||||
DefaultMessage: "Use our Meeting Agenda board template for recurring meetings like standup and our Project Tasks board to manage the progress of tasks along the way.",
|
||||
Illustration: "",
|
||||
},
|
||||
Playbook: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.feature_release.description.playbook",
|
||||
DefaultMessage: "Create transparent workflows across development teams to ensure your feature development process is seamless.",
|
||||
Illustration: "",
|
||||
},
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.feature_release.description.integration",
|
||||
DefaultMessage: "Increase productivity in your channel by integrating a Jira bot and Github bot. These will be downloaded for you.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "feature-release",
|
||||
Name: "Feature Release",
|
||||
Purpose: "",
|
||||
Playbook: "product-release-playbook",
|
||||
Illustration: "/static/worktemplates/product_teams/feature_release/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-meeting-agenda",
|
||||
Template: "54fcf9c610f0ac5e4c522c0657c90602",
|
||||
Name: "Meeting Agenda",
|
||||
Channel: "feature-release",
|
||||
Illustration: "/static/worktemplates/boards/meeting_agenda.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-project-task",
|
||||
Template: "a4ec399ab4f2088b1051c3cdf1dde4c3",
|
||||
Name: "Project Task",
|
||||
Channel: "feature-release",
|
||||
Illustration: "/static/worktemplates/boards/project_tasks.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Playbook: &Playbook{
|
||||
Template: "Product Release",
|
||||
Name: "Feature release",
|
||||
ID: "product-release-playbook",
|
||||
Illustration: "/static/worktemplates/playbooks/product_release.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "jira",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "github",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wt5baa68055bf9ea423273662e01ccc575 = &WorkTemplate{
|
||||
ID: "product_teams/goals_and_okrs:v1",
|
||||
Category: "product_teams",
|
||||
UseCase: "Set goals and OKR's",
|
||||
Illustration: "/static/worktemplates/product_teams/goals_and_okrs/goals_and_okrs.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.goals_and_okrs.channel",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.goals_and_okrs.board",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.goals_and_okrs.integration",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674845108569",
|
||||
Name: "Goals and OKR",
|
||||
Purpose: "",
|
||||
Playbook: "",
|
||||
Illustration: "/static/worktemplates/product_teams/goals_and_okrs/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674845139258",
|
||||
Template: "7ba22ccfdfac391d63dea5c4b8cde0de",
|
||||
Name: "Goals and OKR",
|
||||
Channel: "channel-1674845108569",
|
||||
Illustration: "/static/worktemplates/boards/company_goal_and_okrs.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674845175528",
|
||||
Template: "54fcf9c610f0ac5e4c522c0657c90602",
|
||||
Name: "Meeting Agenda",
|
||||
Channel: "channel-1674845108569",
|
||||
Illustration: "/static/worktemplates/boards/meeting_agenda.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "zoom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wtfeb56bc6a8f277c47b503bd1c92d830e = &WorkTemplate{
|
||||
ID: "product_teams/bug_bash:v1",
|
||||
Category: "product_teams",
|
||||
UseCase: "Run a bug bash",
|
||||
Illustration: "/static/worktemplates/product_teams/bug_bash/bug_bash.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.bug_bash.channel",
|
||||
DefaultMessage: "Get organized and bash all the bugs with this project! Build momentum and measure progress using included Playbook, Board, and Channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.bug_bash.board",
|
||||
DefaultMessage: "Get organized and bash all the bugs with this project! Build momentum and measure progress using included Playbook, Board, and Channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
Playbook: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.bug_bash.playbook",
|
||||
DefaultMessage: "Get organized and bash all the bugs with this project! Build momentum and measure progress using included Playbook, Board, and Channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.bug_bash.integration",
|
||||
DefaultMessage: "Get organized and bash all the bugs with this project! Build momentum and measure progress using included Playbook, Board, and Channel.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Playbook: &Playbook{
|
||||
Template: "Bug Bash",
|
||||
Name: "Bug Bash",
|
||||
ID: "playbook-1674844017943",
|
||||
Illustration: "/static/worktemplates/playbooks/bug_bash.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674844017943",
|
||||
Name: "Bug Bash",
|
||||
Purpose: "",
|
||||
Playbook: "playbook-1674844017943",
|
||||
Illustration: "/static/worktemplates/product_teams/bug_bash/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "jira",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wt8d2ef53deac5517eb349dc5de6150196 = &WorkTemplate{
|
||||
ID: "product_teams/sprint_planning:v1",
|
||||
Category: "product_teams",
|
||||
UseCase: "Plan sprints",
|
||||
Illustration: "/static/worktemplates/product_teams/sprint_planning/sprint_planning.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.sprint_planning.channel",
|
||||
DefaultMessage: "Use a Project to make sprint planning a breeze. The channel keeps the conversation and questions focused. The sprint plan keeps everyone on task for the week and the Retrospective board brings the team together to continuously improve.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.sprint_planning.board",
|
||||
DefaultMessage: "Use a Project to make sprint planning a breeze. The channel keeps the conversation and questions focused. The sprint plan keeps everyone on task for the week and the Retrospective board brings the team together to continuously improve.",
|
||||
Illustration: "",
|
||||
},
|
||||
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.sprint_planning.integration",
|
||||
DefaultMessage: "Use a Project to make sprint planning a breeze. The channel keeps the conversation and questions focused. The sprint plan keeps everyone on task for the week and the Retrospective board brings the team together to continuously improve.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674850783500",
|
||||
Name: "Sprint planning",
|
||||
Purpose: "",
|
||||
Playbook: "",
|
||||
Illustration: "/static/worktemplates/product_teams/sprint_planning/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674850783973",
|
||||
Template: "99b74e26d2f5d0a9b346d43c0a7bfb09",
|
||||
Name: "Sprint planning",
|
||||
Channel: "channel-1674850783500",
|
||||
Illustration: "/static/worktemplates/boards/sprint_planner.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "zoom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wt00ab91a945627f4a624957dd80490bb2 = &WorkTemplate{
|
||||
ID: "product_teams/product_roadmap:v1",
|
||||
Category: "product_teams",
|
||||
UseCase: "Create a product roadmap",
|
||||
Illustration: "/static/worktemplates/product_teams/product_roadmap/product_roadmap.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.product_roadmap.channel",
|
||||
DefaultMessage: "Description of why the channel(s) are needed",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.product_teams.product_roadmap.board",
|
||||
DefaultMessage: "Description of why the board(s) are needed",
|
||||
Illustration: "",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674851139450",
|
||||
Name: "Product Roadmap",
|
||||
Purpose: "",
|
||||
Playbook: "",
|
||||
Illustration: "/static/worktemplates/product_teams/product_roadmap/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674851139759",
|
||||
Template: "b728c6ca730e2cfc229741c5a4712b65",
|
||||
Name: "Product Roadmap",
|
||||
Channel: "channel-1674851139450",
|
||||
Illustration: "/static/worktemplates/boards/roadmap.png",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wtce19b9352a59d6a5d26f292d83e84377 = &WorkTemplate{
|
||||
ID: "devops/incident_resolution:v1",
|
||||
Category: "devops",
|
||||
UseCase: "Resolve incidents",
|
||||
Illustration: "/static/worktemplates/devops/incident_resolution/incident_resolution.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.devops.incident_resolution.description.channel",
|
||||
DefaultMessage: "When everything is going wrong, having a repeatable process is the key to making sure everything is made right as quickly as possible. This Project combines everything Mattermost offers to ensure the fires are put out and stakeholders informed along the way.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.devops.incident_resolution.description.board",
|
||||
DefaultMessage: "When everything is going wrong, having a repeatable process is the key to making sure everything is made right as quickly as possible. This Project combines everything Mattermost offers to ensure the fires are put out and stakeholders informed along the way.",
|
||||
Illustration: "",
|
||||
},
|
||||
Playbook: &TranslatableString{
|
||||
ID: "worktemplate.devops.incident_resolution.description.playbook",
|
||||
DefaultMessage: "When everything is going wrong, having a repeatable process is the key to making sure everything is made right as quickly as possible. This Project combines everything Mattermost offers to ensure the fires are put out and stakeholders informed along the way.",
|
||||
Illustration: "",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Playbook: &Playbook{
|
||||
Template: "Incident Resolution",
|
||||
Name: "Incident Resolution",
|
||||
ID: "irpb",
|
||||
Illustration: "/static/worktemplates/playbooks/incident_resolution.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "irc",
|
||||
Name: "Incident Resolution",
|
||||
Purpose: "",
|
||||
Playbook: "irpb",
|
||||
Illustration: "/static/worktemplates/devops/incident_resolution/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "irb",
|
||||
Template: "a4ec399ab4f2088b1051c3cdf1dde4c3",
|
||||
Name: "Incident Resolution",
|
||||
Channel: "irc",
|
||||
Illustration: "/static/worktemplates/boards/project_tasks.png",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wt37406285a41c18bcdeb881189f7acde0 = &WorkTemplate{
|
||||
ID: "devops/product_release:v1",
|
||||
Category: "devops",
|
||||
UseCase: "Prepare a product release",
|
||||
Illustration: "/static/worktemplates/devops/product_release/product_release.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.devops.product_release.channel",
|
||||
DefaultMessage: "Don’t miss a step during a product release with this Project. Assign tasks from the Playbook checklist and hit milestones with the Board. Use Channels to keep everyone on the same page.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.devops.product_release.board",
|
||||
DefaultMessage: "Don’t miss a step during a product release with this Project. Assign tasks from the Playbook checklist and hit milestones with the Board. Use Channels to keep everyone on the same page.",
|
||||
Illustration: "",
|
||||
},
|
||||
Playbook: &TranslatableString{
|
||||
ID: "worktemplate.devops.product_release.playbook",
|
||||
DefaultMessage: "Don’t miss a step during a product release with this Project. Assign tasks from the Playbook checklist and hit milestones with the Board. Use Channels to keep everyone on the same page.",
|
||||
Illustration: "",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Playbook: &Playbook{
|
||||
Template: "Product Release",
|
||||
Name: "Product Release",
|
||||
ID: "playbook-1674851385983",
|
||||
Illustration: "/static/worktemplates/playbooks/product_release.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674851385983",
|
||||
Name: "Product Release",
|
||||
Purpose: "",
|
||||
Playbook: "playbook-1674851385983",
|
||||
Illustration: "/static/worktemplates/devops/product_release/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674851386432",
|
||||
Template: "a4ec399ab4f2088b1051c3cdf1dde4c3",
|
||||
Name: "Product Release",
|
||||
Channel: "channel-1674851385983",
|
||||
Illustration: "/static/worktemplates/boards/project_tasks.png",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wtf7b846d35810f8272eeb9a1a562025b5 = &WorkTemplate{
|
||||
ID: "companywide/goals_and_okrs:v1",
|
||||
Category: "companywide",
|
||||
UseCase: "Set goals and OKR's",
|
||||
Illustration: "/static/worktemplates/companywide/goals_and_okrs/goals_and_okrs.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.companywide.goals_and_okrs.channel",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.companywide.goals_and_okrs.board",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.companywide.goals_and_okrs.integration",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674845108569",
|
||||
Name: "Goals and OKR",
|
||||
Purpose: "",
|
||||
Playbook: "",
|
||||
Illustration: "/static/worktemplates/companywide/goals_and_okrs/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674845139258",
|
||||
Template: "7ba22ccfdfac391d63dea5c4b8cde0de",
|
||||
Name: "Goals and OKR",
|
||||
Channel: "channel-1674845108569",
|
||||
Illustration: "/static/worktemplates/boards/company_goal_and_okrs.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "zoom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wtb9ab412890c2410c7b49eec8f12e7edc = &WorkTemplate{
|
||||
ID: "companywide/create_project:v1",
|
||||
Category: "companywide",
|
||||
UseCase: "Create a project",
|
||||
Illustration: "/static/worktemplates/companywide/create_project/create_project.svg",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.companywide.create_project.channel",
|
||||
DefaultMessage: "Plan a Roadmap using this Project Board and collaborate on topic in the channel created with this template.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.companywide.create_project.board",
|
||||
DefaultMessage: "Plan a Roadmap using this Project Board and collaborate on topic in the channel created with this template.",
|
||||
Illustration: "",
|
||||
},
|
||||
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.companywide.create_project.integration",
|
||||
DefaultMessage: "Plan a Roadmap using this Project Board and collaborate on topic in the channel created with this template.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674851940114",
|
||||
Name: "Create Project",
|
||||
Purpose: "",
|
||||
Playbook: "",
|
||||
Illustration: "/static/worktemplates/companywide/create_project/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674851940548",
|
||||
Template: "a4ec399ab4f2088b1051c3cdf1dde4c3",
|
||||
Name: "Create Project",
|
||||
Channel: "channel-1674851940114",
|
||||
Illustration: "/static/worktemplates/boards/project_tasks.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "jira",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "github",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "zoom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var wt32ab773bfe021e3d4913931041552559 = &WorkTemplate{
|
||||
ID: "leadership/goals_and_okrs:v1",
|
||||
Category: "leadership",
|
||||
UseCase: "Set goals and OKR's",
|
||||
Illustration: "/static/worktemplates/leadership/goals_and_okrs/goals_and_okrs.png",
|
||||
Visibility: "public",
|
||||
|
||||
Description: Description{
|
||||
Channel: &TranslatableString{
|
||||
ID: "worktemplate.leadership.goals_and_okrs.channel",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
Board: &TranslatableString{
|
||||
ID: "worktemplate.leadership.goals_and_okrs.board",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "",
|
||||
},
|
||||
|
||||
Integration: &TranslatableString{
|
||||
ID: "worktemplate.leadership.goals_and_okrs.integration",
|
||||
DefaultMessage: "Clear focus is essential to team success and with this Project you can document the team’s goals and OKR’s as well as post updates in the dedicated channel.",
|
||||
Illustration: "/static/worktemplates/integrations.png",
|
||||
},
|
||||
},
|
||||
Content: []Content{
|
||||
{
|
||||
Channel: &Channel{
|
||||
ID: "channel-1674845108569",
|
||||
Name: "Goals and OKR",
|
||||
Purpose: "",
|
||||
Playbook: "",
|
||||
Illustration: "/static/worktemplates/leadership/goals_and_okrs/channel.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Board: &Board{
|
||||
ID: "board-1674845139258",
|
||||
Template: "7ba22ccfdfac391d63dea5c4b8cde0de",
|
||||
Name: "Goals and OKR",
|
||||
Channel: "channel-1674845108569",
|
||||
Illustration: "/static/worktemplates/boards/company_goal_and_okrs.png",
|
||||
},
|
||||
},
|
||||
{
|
||||
Integration: &Integration{
|
||||
ID: "zoom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
37
server/channels/app/worktemplates/worktemplates.go
Обычный файл
37
server/channels/app/worktemplates/worktemplates.go
Обычный файл
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
//go:generate go run generator/main.go
|
||||
|
||||
package worktemplates
|
||||
|
||||
var OrderedWorkTemplates = []*WorkTemplate{}
|
||||
var OrderedWorkTemplateCategories = []*WorkTemplateCategory{}
|
||||
|
||||
// T is a placeholder to allow the translation tool to register the strings
|
||||
func T(id string) string {
|
||||
return id
|
||||
}
|
||||
|
||||
func registerWorkTemplate(id string, wt *WorkTemplate) {
|
||||
OrderedWorkTemplates = append(OrderedWorkTemplates, wt)
|
||||
}
|
||||
|
||||
func registerWorkTemplateCategory(id string, wtc *WorkTemplateCategory) {
|
||||
OrderedWorkTemplateCategories = append(OrderedWorkTemplateCategories, wtc)
|
||||
}
|
||||
|
||||
func ListCategories() ([]*WorkTemplateCategory, error) {
|
||||
return OrderedWorkTemplateCategories, nil
|
||||
}
|
||||
|
||||
func ListByCategory(category string) ([]*WorkTemplate, error) {
|
||||
wts := []*WorkTemplate{}
|
||||
for i := range OrderedWorkTemplates {
|
||||
if OrderedWorkTemplates[i].Category == category {
|
||||
wts = append(wts, OrderedWorkTemplates[i])
|
||||
}
|
||||
}
|
||||
|
||||
return wts, nil
|
||||
}
|
||||
Ссылка в новой задаче
Block a user