Doug Lauder
2023-03-22 17:22:27 -04:00
коммит произвёл GitHub
родитель b61c096497
Коммит c943ed6859
13276 изменённых файлов: 1695615 добавлений и 223189 удалений

Просмотреть файл

@@ -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

Просмотреть файл

@@ -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

Просмотреть файл

@@ -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 Обычный файл
Просмотреть файл

@@ -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"`
}

Просмотреть файл

@@ -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)
})
}

Просмотреть файл

@@ -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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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: Dont 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: Dont 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: Dont 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 Обычный файл
Просмотреть файл

@@ -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)
}

Просмотреть файл

@@ -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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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: "Dont 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: "Dont 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: "Dont 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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 teams goals and OKRs 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",
},
},
},
}

Просмотреть файл

@@ -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
}