Prevent boards product from being included automatically (#23539)

* Prevent boards product from being included automatically

* Fix config diff test

* Update prepackaged plugin version

Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>

* Readd boards/dist to the gitignore

* Does not enable the focalboard plugin by default

* Update plugin version to v7.10.3

---------

Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>
This commit is contained in:
Miguel de la Cruz 2023-06-12 18:51:43 +02:00 committed by GitHub
parent d8cb5f3a6e
commit 1215584665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 708 additions and 8807 deletions

View File

@ -131,21 +131,6 @@ export default class Client extends Client4 {
return this.doFetch<PluginManifest>(this.getPluginsRoute(), options);
};
// *****************************************************************************
// Boards client
// based on "webapp/boards/src/octoClient.ts"
// *****************************************************************************
async patchUserConfig(userID: string, patch: UserConfigPatch): Promise<UserPreference[] | undefined> {
const path = `/users/${encodeURIComponent(userID)}/config`;
const options = {
method: 'put',
body: JSON.stringify(patch),
};
return this.doFetch<UserPreference[]>(this.getBoardsRoute() + path, options);
}
}
// Variable to hold cache
@ -168,9 +153,6 @@ async function makeClient(userRequest?: UserRequest, useCache = true): Promise<C
const userProfile = await client.login(userRequest.username, userRequest.password);
const user = {...userProfile, password: userRequest.password};
// Manually do until boards as product is consistent in all the codebase.
client.setUseBoardsProduct(true);
if (useCache) {
clients[cacheKey] = {client, user};
}
@ -197,18 +179,4 @@ type ClientCache = {
user: UserProfile | null;
};
// Boards types
interface UserPreference {
user_id: string;
category: string;
name: string;
value: any;
}
interface UserConfigPatch {
updatedFields?: Record<string, string>;
deletedFields?: string[];
}
export {Client, makeClient};

View File

@ -14,20 +14,10 @@ import {getOnPremServerConfig} from './default_config';
import {createRandomTeam} from './team';
import {createRandomUser} from './user';
const boardsUserConfigPatch = {
updatedFields: {
welcomePageViewed: '1',
onboardingTourStep: '999',
tourCategory: 'board',
version72MessageCanceled: 'true',
},
};
export async function initSetup({
userPrefix = 'user',
teamPrefix = {name: 'team', displayName: 'Team'},
withDefaultProfileImage = true,
skipBoardsUserConfig = true,
} = {}) {
try {
// Login the admin user via API
@ -65,10 +55,6 @@ export async function initSetup({
];
await userClient.savePreferences(user.id, preferences);
if (skipBoardsUserConfig) {
await userClient.patchUserConfig(user.id, boardsUserConfigPatch);
}
return {
adminClient,
adminUser,

View File

@ -147,8 +147,7 @@ DIST_PATH_WIN=$(DIST_ROOT)/windows/mattermost
TESTS=.
# Packages lists
TE_PACKAGES=$(shell $(GO) list ./... | grep -vE 'server/v8/playbooks|server/v8/boards|server/v8/cmd/mmctl')
BOARDS_PACKAGES=$(shell $(GO) list ./... | grep -E 'server/v8/boards')
TE_PACKAGES=$(shell $(GO) list ./... | grep -vE 'server/v8/playbooks|server/v8/cmd/mmctl')
PLAYBOOKS_PACKAGES=$(shell $(GO) list ./... | grep -E 'server/v8/playbooks')
SUITE_PACKAGES=$(shell $(GO) list ./...| grep -vE 'server/v8/cmd/mmctl')
MMCTL_PACKAGES=$(shell $(GO) list ./... | grep -E 'server/v8/cmd/mmctl')
@ -173,6 +172,7 @@ PLUGIN_PACKAGES += mattermost-plugin-todo-v0.6.1
PLUGIN_PACKAGES += mattermost-plugin-welcomebot-v1.3.0
PLUGIN_PACKAGES += mattermost-plugin-zoom-v1.6.0
PLUGIN_PACKAGES += mattermost-plugin-apps-v1.2.1
PLUGIN_PACKAGES += focalboard-v7.10.3
# Prepares the enterprise build if exists. The IGNORE stuff is a hack to get the Makefile to execute the commands outside a target
ifeq ($(BUILD_ENTERPRISE_READY),true)
@ -187,9 +187,9 @@ endif
EE_PACKAGES=$(shell $(GO) list $(BUILD_ENTERPRISE_DIR)/...)
ifeq ($(BUILD_ENTERPRISE_READY),true)
ALL_PACKAGES=$(TE_PACKAGES) $(BOARDS_PACKAGES) $(PLAYBOOKS_PACKAGES) $(EE_PACKAGES)
ALL_PACKAGES=$(TE_PACKAGES) $(PLAYBOOKS_PACKAGES) $(EE_PACKAGES)
else
ALL_PACKAGES=$(TE_PACKAGES) $(BOARDS_PACKAGES) $(PLAYBOOKS_PACKAGES)
ALL_PACKAGES=$(TE_PACKAGES) $(PLAYBOOKS_PACKAGES)
endif
all: run ## Alias for 'run'.
@ -326,10 +326,6 @@ app-layers: ## Extract interface from App struct
$(GOBIN)/struct2interface -f "channels/app" -o "channels/app/app_iface.go" -p "app" -s "App" -i "AppIface" -t ./channels/app/layer_generators/app_iface.go.tmpl
$(GO) run ./channels/app/layer_generators -in ./channels/app/app_iface.go -out ./channels/app/opentracing/opentracing_layer.go -template ./channels/app/layer_generators/opentracing_layer.go.tmpl
boards-gen: ## Run generators for Boards
$(GO) install github.com/golang/mock/mockgen@v1.6.0
cd boards && $(GO) generate ./...
i18n-extract: ## Extract strings for translation from the source code
$(GO) install github.com/mattermost/mattermost-utilities/mmgotool@mono-repo
$(GOBIN)/mmgotool i18n extract --portal-dir=""
@ -406,7 +402,7 @@ pluginapi: ## Generates api and hooks glue code for plugins
mocks: store-mocks telemetry-mocks filestore-mocks ldap-mocks plugin-mocks einterfaces-mocks searchengine-mocks sharedchannel-mocks misc-mocks email-mocks platform-mocks mmctl-mocks
layers: app-layers store-layers pluginapi boards-gen
layers: app-layers store-layers pluginapi
generated: mocks layers
@ -463,7 +459,6 @@ endif
test-server-race: test-server-pre
./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(TE_PACKAGES) $(EE_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m"
./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(BOARDS_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m"
./scripts/test.sh "$(GO)" "-race $(GOFLAGS)" "$(PLAYBOOKS_PACKAGES)" "$(TESTS)" "$(TESTFLAGS)" "$(GOBIN)" "90m"
ifneq ($(IS_CI),true)
ifneq ($(MM_NO_DOCKER),true)

View File

@ -21,8 +21,10 @@ const (
boardsProductID = "com.mattermost.boards"
)
//nolint:unused
var errServiceTypeAssert = errors.New("type assertion failed")
/*
func init() {
product.RegisterProduct(boardsProductName, product.Manifest{
Initializer: newBoardsProduct,
@ -49,6 +51,7 @@ func init() {
},
})
}
*/
type boardsProduct struct {
teamService product.TeamService
@ -61,7 +64,7 @@ type boardsProduct struct {
configService product.ConfigService
logger mlog.LoggerIFace
licenseService product.LicenseService
filestoreService product.FilestoreService
filestoreService product.FilestoreService //nolint:unused
fileInfoStoreService product.FileInfoStoreService
routerService product.RouterService
cloudService product.CloudService
@ -74,6 +77,7 @@ type boardsProduct struct {
boardsApp *server.BoardsService
}
//nolint:unused
func newBoardsProduct(services map[product.ServiceKey]interface{}) (product.Product, error) {
boardsProd := &boardsProduct{}
@ -99,6 +103,8 @@ func newBoardsProduct(services map[product.ServiceKey]interface{}) (product.Prod
}
// populateServices populates the boardProduct with all the services needed from the suite.
//
//nolint:unused
func populateServices(boardsProd *boardsProduct, services map[product.ServiceKey]interface{}) error {
for key, service := range services {
switch key {

View File

@ -107,7 +107,6 @@ var pluginIDBlocklist = map[string]bool{
"playbooks": true,
"com.mattermost.plugin-incident-response": true,
"com.mattermost.plugin-incident-management": true,
"focalboard": true,
}
func PluginIDIsBlocked(id string) bool {

View File

@ -58,11 +58,9 @@ build: node_modules ## Builds all web app packages
npm run build
.PHONY: dist
dist: build ## Builds all web app packages and copies Boards/Playbooks files into Channels dist folder
dist: build ## Builds all web app packages and copies Playbooks files into Channels dist folder
@echo Packaging Mattermost Web App
mkdir -p channels/dist/products/boards
cp -R boards/dist/* channels/dist/products/boards
mkdir -p channels/dist/products/playbooks
cp -R playbooks/dist/* channels/dist/products/playbooks

View File

@ -1,6 +1,6 @@
# Mattermost Web App
This folder contains the client code for the Mattermost web app. It's broken up into multiple packages each of which either contains an area of the app (such as `playbooks` or `boards`) or shared logic used across other packages (such as the packages located in the `platform` directory). For anyone who's used to working in [the mattermost/mattermost-webapp repo](https://github.com/mattermost/mattermost-webapp), most of that is now located in `channels`.
This folder contains the client code for the Mattermost web app. It's broken up into multiple packages each of which either contains an area of the app (such as `playbooks`) or shared logic used across other packages (such as the packages located in the `platform` directory). For anyone who's used to working in [the mattermost/mattermost-webapp repo](https://github.com/mattermost/mattermost-webapp), most of that is now located in `channels`.
## npm Workspaces
@ -8,7 +8,7 @@ To interact with a workspace using npm, such as to add a dependency or run a scr
```sh
# Add a dependency to a single package
npm add react --workspace=boards
npm add react --workspace=playbooks
# Build multiple packages
npm run build --workspace=platform/client --workspace=platform/components

View File

@ -1,44 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Client4} from 'mattermost-redux/client';
import testConfigureStore from 'tests/test_store';
import {initializeProducts} from './products';
(window as any).REMOTE_CONTAINERS = {};
describe('initializeProducts', () => {
test('should set Client4 to use the correct Boards URL for product mode', async () => {
const store = testConfigureStore({
entities: {
general: {
config: {
FeatureFlagBoardsProduct: 'true',
},
},
},
});
await store.dispatch(initializeProducts());
expect(Client4.getBoardsRoute().startsWith('/plugins/boards')).toBe(true);
});
test('should set Client4 to use the correct Boards URL for plugin mode', async () => {
const store = testConfigureStore({
entities: {
general: {
config: {
FeatureFlagBoardsProduct: 'false',
},
},
},
});
await store.dispatch(initializeProducts());
expect(Client4.getBoardsRoute().startsWith('/plugins/focalboard')).toBe(true);
});
});

View File

@ -3,7 +3,6 @@
import {Store} from 'redux';
import {Client4} from 'mattermost-redux/client';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions';
@ -26,11 +25,8 @@ export function initializeProducts() {
}
function configureClient() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return (dispatch: DispatchFunc, getState: GetStateFunc) => {
const config = getConfig(getState());
Client4.setUseBoardsProduct(config.FeatureFlagBoardsProduct === 'true');
return Promise.resolve({data: true});
};
}
@ -48,20 +44,10 @@ function loadRemoteModules() {
* can't be constructed based on the name of a product at runtime.
*/
let products = [
{
id: 'boards',
load: () => ({
index: import('boards'),
// manifest: import('boards/manifest'),
}),
},
{
id: 'playbooks',
load: () => ({
index: import('playbooks'),
// manifest: import('boards/manifest'),
}),
},
];

View File

@ -279,15 +279,10 @@ if (DEV) {
config.plugins.push({
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', () => {
const boardsDist = path.resolve(__dirname, '../boards/dist');
const boardsSymlink = './dist/products/boards';
const playbooksDist = path.resolve(__dirname, '../playbooks/dist');
const playbooksSymlink = './dist/products/playbooks';
fs.mkdir('./dist/products', () => {
if (!fs.existsSync(boardsSymlink)) {
fs.symlinkSync(boardsDist, boardsSymlink, 'dir');
}
if (!fs.existsSync(playbooksSymlink)) {
fs.symlinkSync(playbooksDist, playbooksSymlink, 'dir');
}
@ -334,7 +329,6 @@ async function initializeModuleFederation() {
async function getRemoteContainers() {
const products = [
{name: 'boards'},
{name: 'playbooks'},
];

9342
webapp/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,6 @@
"platform/client",
"platform/components",
"platform/types",
"playbooks",
"boards"
"playbooks"
]
}

View File

@ -182,8 +182,6 @@ export default class Client4 {
userRoles = '';
telemetryHandler?: TelemetryHandler;
useBoardsProduct = false;
getUrl() {
return this.url;
}
@ -247,10 +245,6 @@ export default class Client4 {
this.telemetryHandler = telemetryHandler;
}
setUseBoardsProduct(useBoardsProduct: boolean) {
this.useBoardsProduct = useBoardsProduct;
}
getServerVersion() {
return this.serverVersion;
}
@ -479,10 +473,6 @@ export default class Client4 {
return `${this.getBaseRoute()}/drafts`;
}
getBoardsRoute() {
return `${this.url}/plugins/${this.useBoardsProduct ? 'boards' : 'focalboard'}/api/v2`;
}
getCSRFFromCookie() {
if (typeof document !== 'undefined' && typeof document.cookie !== 'undefined') {
const cookies = document.cookie.split(';');

View File

@ -41,20 +41,6 @@ async function buildAll() {
console.log('\n' + chalk.inverse.bold('Web app built! '));
console.log(chalk.inverse.bold('Building Boards...') + '\n');
try {
const {result} = concurrently([
{command: 'npm:build --workspace=boards', name: 'boards', prefixColor: 'blue'},
]);
await result;
} catch (e) {
console.error(chalk.inverse.bold.red('Failed to build Boards'), e);
return;
}
console.log('\n' + chalk.inverse.bold('Boards built! '));
console.log(chalk.inverse.bold('Building Playbooks...') + '\n');
try {

View File

@ -13,7 +13,6 @@ async function watchAllWithDevServer() {
const commands = [
{command: 'npm:dev-server --workspace=channels', name: 'webapp', prefixColor: 'cyan'},
{command: 'npm:start:product --workspace=boards', name: 'boards', prefixColor: 'blue'},
{command: 'npm:start:product --workspace=playbooks', name: 'playbooks', prefixColor: 'red'},
];

View File

@ -16,7 +16,6 @@ async function watchAll(useRunner) {
const commands = [
{command: 'npm:run --workspace=channels', name: 'webapp', prefixColor: 'cyan'},
{command: 'npm:start:product --workspace=boards', name: 'boards', prefixColor: 'blue'},
{command: 'npm:start:product --workspace=playbooks', name: 'playbooks', prefixColor: 'red'},
];