MM-46274 Add ability to run Boards as a product in development
This commit is contained in:
parent
765fbc88e9
commit
d462d9a5d7
8 changed files with 2458 additions and 227 deletions
3
Makefile
3
Makefile
|
@ -186,6 +186,9 @@ watch-plugin: modd-precheck ## Run and upload the plugin to a development server
|
||||||
live-watch-plugin: modd-precheck ## Run and update locally the plugin in the development server
|
live-watch-plugin: modd-precheck ## Run and update locally the plugin in the development server
|
||||||
cd mattermost-plugin; make live-watch
|
cd mattermost-plugin; make live-watch
|
||||||
|
|
||||||
|
watch-product: ## Run the product as something the Mattermost web app will watch for
|
||||||
|
cd mattermost-plugin; make watch-product
|
||||||
|
|
||||||
mac-app: server-mac webapp ## Build Mac application.
|
mac-app: server-mac webapp ## Build Mac application.
|
||||||
rm -rf mac/temp
|
rm -rf mac/temp
|
||||||
rm -rf mac/dist
|
rm -rf mac/dist
|
||||||
|
|
|
@ -84,7 +84,7 @@ ifneq ($(HAS_SERVER),)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
templates-archive: setup-go-work ## Build templates archive file
|
templates-archive: setup-go-work ## Build templates archive file
|
||||||
cd ../server/assets/build-template-archive; go run -tags '$(BUILD_TAGS)' main.go --dir="../templates-boardarchive" --out="../templates.boardarchive"
|
cd ../server/assets/build-template-archive; go run -tags '$(BUILD_TAGS)' main.go --dir="../templates-boardarchive" --out="../templates.boardarchive"
|
||||||
|
|
||||||
## Builds the server, if it exists, for all supported architectures.
|
## Builds the server, if it exists, for all supported architectures.
|
||||||
.PHONY: server
|
.PHONY: server
|
||||||
|
@ -175,6 +175,10 @@ endif
|
||||||
deploy-from-watch: bundle
|
deploy-from-watch: bundle
|
||||||
./build/bin/pluginctl deploy $(PLUGIN_ID) dist/$(BUNDLE_NAME)
|
./build/bin/pluginctl deploy $(PLUGIN_ID) dist/$(BUNDLE_NAME)
|
||||||
|
|
||||||
|
.PHONE: watch-product
|
||||||
|
watch-product: apply
|
||||||
|
cd webapp && npm run start:product
|
||||||
|
|
||||||
## Setup dlv for attaching, identifying the plugin PID for other targets.
|
## Setup dlv for attaching, identifying the plugin PID for other targets.
|
||||||
.PHONY: setup-attach
|
.PHONY: setup-attach
|
||||||
setup-attach:
|
setup-attach:
|
||||||
|
|
2543
mattermost-plugin/webapp/package-lock.json
generated
2543
mattermost-plugin/webapp/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,8 @@
|
||||||
"test": "jest --forceExit --detectOpenHandles --verbose",
|
"test": "jest --forceExit --detectOpenHandles --verbose",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test-ci": "jest --forceExit --detectOpenHandles --maxWorkers=2",
|
"test-ci": "jest --forceExit --detectOpenHandles --maxWorkers=2",
|
||||||
"check-types": "tsc"
|
"check-types": "tsc",
|
||||||
|
"start:product": "webpack serve --mode=development"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.17.6",
|
"@babel/cli": "7.17.6",
|
||||||
|
@ -78,7 +79,8 @@
|
||||||
"ts-loader": "9.2.8",
|
"ts-loader": "9.2.8",
|
||||||
"typescript": "4.6.2",
|
"typescript": "4.6.2",
|
||||||
"webpack": "5.70.0",
|
"webpack": "5.70.0",
|
||||||
"webpack-cli": "4.9.2"
|
"webpack-cli": "4.10.0",
|
||||||
|
"webpack-dev-server": "4.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "3.21.1",
|
"core-js": "3.21.1",
|
||||||
|
|
|
@ -14,9 +14,8 @@ import {selectTeam} from 'mattermost-redux/actions/teams'
|
||||||
import {SuiteWindow} from '../../../webapp/src/types/index'
|
import {SuiteWindow} from '../../../webapp/src/types/index'
|
||||||
import {UserSettings} from '../../../webapp/src/userSettings'
|
import {UserSettings} from '../../../webapp/src/userSettings'
|
||||||
|
|
||||||
|
|
||||||
const windowAny = (window as SuiteWindow)
|
const windowAny = (window as SuiteWindow)
|
||||||
windowAny.baseURL = '/plugins/focalboard'
|
windowAny.baseURL = process.env.TARGET_IS_PRODUCT ? '/plugins/boards' : '/plugins/focalboard'
|
||||||
windowAny.frontendBaseURL = '/boards'
|
windowAny.frontendBaseURL = '/boards'
|
||||||
windowAny.isFocalboardPlugin = true
|
windowAny.isFocalboardPlugin = true
|
||||||
|
|
||||||
|
@ -334,7 +333,7 @@ export default class Plugin {
|
||||||
const data = await octoClient.getMyTopBoards(timeRange, page, perPage, teamId)
|
const data = await octoClient.getMyTopBoards(timeRange, page, perPage, teamId)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await octoClient.getTeamTopBoards(timeRange, page, perPage, teamId)
|
const data = await octoClient.getTeamTopBoards(timeRange, page, perPage, teamId)
|
||||||
|
|
||||||
|
@ -408,11 +407,3 @@ export default class Plugin {
|
||||||
this.registry?.unregisterWebSocketEventHandler(wsClient.clientPrefix + ACTION_UPDATE_BLOCK)
|
this.registry?.unregisterWebSocketEventHandler(wsClient.clientPrefix + ACTION_UPDATE_BLOCK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
registerPlugin(id: string, plugin: Plugin): void
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.registerPlugin(manifest.id, new Plugin())
|
|
||||||
|
|
14
mattermost-plugin/webapp/src/plugin_entry.ts
Normal file
14
mattermost-plugin/webapp/src/plugin_entry.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import manifest from './manifest'
|
||||||
|
|
||||||
|
import Plugin from './index'
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
registerPlugin(id: string, plugin: Plugin): void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.registerPlugin(manifest.id, new Plugin())
|
4
mattermost-plugin/webapp/src/remote_entry.ts
Normal file
4
mattermost-plugin/webapp/src/remote_entry.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import('./index')
|
|
@ -5,16 +5,21 @@ const exec = require('child_process').exec;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
|
const {ModuleFederationPlugin} = require('webpack').container;
|
||||||
|
|
||||||
const tsTransformer = require('@formatjs/ts-transformer');
|
const tsTransformer = require('@formatjs/ts-transformer');
|
||||||
|
|
||||||
const PLUGIN_ID = require('../plugin.json').id;
|
const PLUGIN_ID = require('../plugin.json').id;
|
||||||
|
|
||||||
|
const packageJson = require('./package.json');
|
||||||
|
|
||||||
const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env
|
const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env
|
||||||
|
const TARGET_IS_PRODUCT = NPM_TARGET === 'start:product' || NPM_TARGET === 'build:product';
|
||||||
|
|
||||||
let mode = 'production';
|
let mode = 'production';
|
||||||
let devtool;
|
let devtool;
|
||||||
const plugins = [];
|
const plugins = [];
|
||||||
if (NPM_TARGET === 'debug' || NPM_TARGET === 'debug:watch') {
|
if (NPM_TARGET === 'debug' || NPM_TARGET === 'debug:watch' || NPM_TARGET === 'start:product') {
|
||||||
mode = 'development';
|
mode = 'development';
|
||||||
devtool = 'source-map';
|
devtool = 'source-map';
|
||||||
plugins.push(
|
plugins.push(
|
||||||
|
@ -49,10 +54,8 @@ if (NPM_TARGET === 'build:watch' || NPM_TARGET === 'debug:watch' || NPM_TARGET =
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
const config = {
|
||||||
entry: [
|
entry: TARGET_IS_PRODUCT ? './src/remote_entry.ts' : './src/plugin_entry.ts',
|
||||||
'./src/index.tsx',
|
|
||||||
],
|
|
||||||
resolve: {
|
resolve: {
|
||||||
modules: [
|
modules: [
|
||||||
'src',
|
'src',
|
||||||
|
@ -61,7 +64,6 @@ module.exports = {
|
||||||
],
|
],
|
||||||
alias: {
|
alias: {
|
||||||
moment: path.resolve(__dirname, '../../webapp/node_modules/moment/'),
|
moment: path.resolve(__dirname, '../../webapp/node_modules/moment/'),
|
||||||
'react-intl': path.resolve(__dirname, '../../webapp/node_modules/react-intl/'),
|
|
||||||
},
|
},
|
||||||
extensions: ['*', '.js', '.jsx', '.ts', '.tsx'],
|
extensions: ['*', '.js', '.jsx', '.ts', '.tsx'],
|
||||||
},
|
},
|
||||||
|
@ -120,30 +122,80 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
externals: {
|
|
||||||
react: 'React',
|
|
||||||
redux: 'Redux',
|
|
||||||
'react-redux': 'ReactRedux',
|
|
||||||
'mm-react-router-dom': 'ReactRouterDom',
|
|
||||||
'prop-types': 'PropTypes',
|
|
||||||
'react-bootstrap': 'ReactBootstrap',
|
|
||||||
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
devtoolNamespace: PLUGIN_ID,
|
|
||||||
path: path.join(__dirname, '/dist'),
|
|
||||||
publicPath: '/',
|
|
||||||
filename: 'main.js',
|
|
||||||
},
|
|
||||||
devtool,
|
devtool,
|
||||||
mode,
|
mode,
|
||||||
plugins,
|
plugins,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (TARGET_IS_PRODUCT) {
|
||||||
|
function makeSingletonSharedModules(packageNames) {
|
||||||
|
const sharedObject = {};
|
||||||
|
|
||||||
|
for (const packageName of packageNames) {
|
||||||
|
const version = packageJson.dependencies[packageName];
|
||||||
|
|
||||||
|
sharedObject[packageName] = {
|
||||||
|
requiredVersion: version,
|
||||||
|
singleton: true,
|
||||||
|
version,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return sharedObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.plugins.push(new ModuleFederationPlugin({
|
||||||
|
name: PLUGIN_ID,
|
||||||
|
filename: 'remote_entry.js',
|
||||||
|
exposes: {
|
||||||
|
'.': './src/index',
|
||||||
|
|
||||||
|
// This probably won't need to be exposed in the long run, but its a POC for exposing multiple modules
|
||||||
|
'./manifest': './src/manifest',
|
||||||
|
},
|
||||||
|
shared: [
|
||||||
|
'@mattermost/client',
|
||||||
|
'prop-types',
|
||||||
|
|
||||||
|
makeSingletonSharedModules([
|
||||||
|
'react',
|
||||||
|
'react-dom',
|
||||||
|
'react-intl',
|
||||||
|
'react-redux',
|
||||||
|
'react-router-dom',
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
|
config.plugins.push(new webpack.DefinePlugin({
|
||||||
|
'process.env.TARGET_IS_PRODUCT': TARGET_IS_PRODUCT, // TODO We might want a better name for this
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
config.resolve.alias['react-intl'] = path.resolve(__dirname, '../../webapp/node_modules/react-intl/');
|
||||||
|
|
||||||
|
config.outputs = {
|
||||||
|
devtoolNamespace: PLUGIN_ID,
|
||||||
|
path: path.join(__dirname, '/dist'),
|
||||||
|
publicPath: '/',
|
||||||
|
filename: 'main.js',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const env = {};
|
const env = {};
|
||||||
env.RUDDER_KEY = JSON.stringify(process.env.RUDDER_KEY || ''); //eslint-disable-line no-process-env
|
env.RUDDER_KEY = JSON.stringify(process.env.RUDDER_KEY || ''); //eslint-disable-line no-process-env
|
||||||
env.RUDDER_DATAPLANE_URL = JSON.stringify(process.env.RUDDER_DATAPLANE_URL || ''); //eslint-disable-line no-process-env
|
env.RUDDER_DATAPLANE_URL = JSON.stringify(process.env.RUDDER_DATAPLANE_URL || ''); //eslint-disable-line no-process-env
|
||||||
|
|
||||||
module.exports.plugins.push(new webpack.DefinePlugin({
|
config.plugins.push(new webpack.DefinePlugin({
|
||||||
'process.env': env,
|
'process.env': env,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (NPM_TARGET === 'start:product') {
|
||||||
|
config.devServer = {
|
||||||
|
port: 9006,
|
||||||
|
devMiddleware: {
|
||||||
|
writeToDisk: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
|
|
Loading…
Reference in a new issue