commit
8f5c9eadf6
22 changed files with 7999 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
dist
|
9
CHANGELOG.md
Normal file
9
CHANGELOG.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.0.1 - 2018-08-16
|
||||
### Added
|
||||
- Initial release
|
201
LICENSE
Normal file
201
LICENSE
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
112
Makefile
Normal file
112
Makefile
Normal file
|
@ -0,0 +1,112 @@
|
|||
GO=$(shell go env GOPATH)/bin/vgo
|
||||
|
||||
# Check that vgo is installed. This won't be necessary once Go 1.11 is released, but it will still
|
||||
# be necessary to assert the Go version.
|
||||
ifeq ($(GO),)
|
||||
echo go get -u github.com/golang/vgo; \
|
||||
go get -u github.com/golang/vgo;
|
||||
endif
|
||||
|
||||
# Ensure that the build tools are compiled. Go's caching makes this quick.
|
||||
$(shell cd build/manifest && $(GO) build -o ../bin/manifest)
|
||||
|
||||
# Extract the plugin id from the manifest.
|
||||
PLUGIN_ID=$(shell build/bin/manifest plugin_id)
|
||||
ifeq ($(PLUGIN_ID),)
|
||||
$(error Cannot parse id from plugin.json)
|
||||
endif
|
||||
|
||||
# Determine if a server is defined in plugin.json
|
||||
HAS_SERVER=$(shell build/bin/manifest has_server)
|
||||
|
||||
# Determine if a webapp is defined in plugin.json
|
||||
HAS_WEBAPP=$(shell build/bin/manifest has_webapp)
|
||||
|
||||
# all, the default target, builds and bundle the plugin.
|
||||
all: dist
|
||||
|
||||
# apply propagates the plugin id into the server/ and webapp/ folders as required.
|
||||
.PHONY: apply
|
||||
apply:
|
||||
./build/bin/manifest apply
|
||||
|
||||
# server builds the server, if it exists, including support for multiple architectures
|
||||
.PHONY: server
|
||||
server:
|
||||
ifneq ($(HAS_SERVER),)
|
||||
mkdir -p server/dist;
|
||||
cd server && env GOOS=linux GOARCH=amd64 $(GO) build -o dist/plugin-linux-amd64;
|
||||
cd server && env GOOS=darwin GOARCH=amd64 $(GO) build -o dist/plugin-darwin-amd64;
|
||||
cd server && env GOOS=windows GOARCH=amd64 $(GO) build -o dist/plugin-windows-amd64.exe;
|
||||
endif
|
||||
|
||||
# webapp/.npminstall ensures NPM dependencies are installed without having to run this all the time
|
||||
webapp/.npminstall:
|
||||
ifneq ($(HAS_WEBAPP),)
|
||||
cd webapp && npm install
|
||||
touch $@
|
||||
endif
|
||||
|
||||
# webapp builds the webapp, if it exists
|
||||
.PHONY: webapp
|
||||
webapp: webapp/.npminstall
|
||||
ifneq ($(HAS_WEBAPP),)
|
||||
cd webapp && npm run fix;
|
||||
cd webapp && npm run build;
|
||||
endif
|
||||
|
||||
# bundle generates a tar bundle of the plugin for install
|
||||
.PHONY: bundle
|
||||
bundle:
|
||||
rm -rf dist/
|
||||
mkdir -p dist/$(PLUGIN_ID)
|
||||
cp plugin.json dist/$(PLUGIN_ID)/
|
||||
ifneq ($(HAS_SERVER),)
|
||||
mkdir -p dist/$(PLUGIN_ID)/server/dist;
|
||||
cp -r server/dist/* dist/$(PLUGIN_ID)/server/dist/;
|
||||
endif
|
||||
ifneq ($(HAS_WEBAPP),)
|
||||
mkdir -p dist/$(PLUGIN_ID)/webapp/dist;
|
||||
cp -r webapp/dist/* dist/$(PLUGIN_ID)/webapp/dist/;
|
||||
endif
|
||||
cd dist/$(PLUGIN_ID) && tar -zcvf ../$(PLUGIN_ID).tar.gz *
|
||||
|
||||
@echo plugin built at: dist/$(PLUGIN_ID).tar.gz
|
||||
|
||||
# dist builds and bundles the plugin
|
||||
.PHONY: dist
|
||||
dist: apply \
|
||||
server \
|
||||
webapp \
|
||||
bundle
|
||||
|
||||
# deploy installs the plugin to a (development) server, using the API if appropriate environment
|
||||
# variables are defined, or copying the files directly to a sibling mattermost-server directory
|
||||
.PHONY: deploy
|
||||
deploy:
|
||||
ifneq ($(and $(MM_SERVICESETTINGS_SITEURL),$(MM_ADMIN_USERNAME),$(MM_ADMIN_PASSWORD)),)
|
||||
@echo "Installing plugin via API"
|
||||
http --print b --check-status $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/me || ( \
|
||||
TOKEN=`http --print h POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/login login_id=$(MM_ADMIN_USERNAME) password=$(MM_ADMIN_PASSWORD) | grep Token | cut -f2 -d' '` && \
|
||||
http --print b GET $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/me Authorization:"Bearer $$TOKEN" \
|
||||
)
|
||||
http --print b DELETE $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)
|
||||
http --print b --check-status --form POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins plugin@dist/$(PLUGIN_ID).tar.gz && \
|
||||
http --print b POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/enable
|
||||
else ifneq ($(wildcard ../mattermost-server/.*),)
|
||||
@echo "Installing plugin via filesystem. Server restart and manual plugin enabling required"
|
||||
mkdir -p ../mattermost-server/plugins/$(PLUGIN_ID)
|
||||
tar -C ../mattermost-server/plugins/$(PLUGIN_ID) -zxvf dist/$(PLUGIN_ID).tar.gz
|
||||
else
|
||||
@echo "No supported deployment method available. Install plugin manually."
|
||||
endif
|
||||
|
||||
# clean removes all build artifacts
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -fr dist/
|
||||
rm -fr server/dist
|
||||
rm -fr webapp/.npminstall
|
||||
rm -fr webapp/dist
|
||||
rm -fr webapp/node_modules
|
||||
rm -fr build/bin/
|
47
README.md
Normal file
47
README.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Sample Plugin
|
||||
|
||||
This plugin serves as a starting point for writing a Mattermost plugin. Feel free to base your own plugin off this repository.
|
||||
|
||||
## Getting Started
|
||||
Shallow clone the repository to a directory matching your plugin name:
|
||||
```
|
||||
git clone --depth 1 https://github.com/mattermost/mattermost-plugin-sample com.example.my-plugin
|
||||
```
|
||||
|
||||
Edit `plugin.json` with your `id`, `name`, and `description`:
|
||||
```
|
||||
{
|
||||
"id": "com.example.my-plugin",
|
||||
"name": "My Plugin",
|
||||
"description": "A plugin to enhance Mattermost."
|
||||
}
|
||||
```
|
||||
|
||||
Build your plugin:
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
This will produce a single plugin file (with support for multiple architectures) for upload to your Mattermost server:
|
||||
|
||||
```
|
||||
dist/com.example.my-plugin.tar.gz
|
||||
```
|
||||
|
||||
There is a build target to automate deploying and enabling the plugin to your server, but it requires configuration and [http](https://httpie.org/) to be installed:
|
||||
```
|
||||
export MM_SERVICESETTINGS_SITEURL=http://localhost:8065/
|
||||
export MM_ADMIN_USERNAME=admin
|
||||
export MM_ADMIN_PASSWORD=password
|
||||
make deploy
|
||||
```
|
||||
|
||||
Alternatively, if you are running your `mattermost-server` out of a sibling directory by the same name, use the `deploy` target alone to unpack the files into the right directory. You will need to restart your server and manually enable your plugin.
|
||||
|
||||
In production, deploy and upload your plugin via the [System Console](https://about.mattermost.com/default-plugin-uploads).
|
||||
|
||||
## Q&A
|
||||
|
||||
### How do I make a server-only or web app-only plugin?
|
||||
|
||||
Simply delete the `server` or `webapp` folders and remove the corresponding sections from `plugin.json`. The build scripts will skip the missing portions automatically.
|
1
build/.gitignore
vendored
Normal file
1
build/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
bin
|
17
build/manifest/go.mod
Normal file
17
build/manifest/go.mod
Normal file
|
@ -0,0 +1,17 @@
|
|||
module github.com/mattermost/mattermost-plugin-sample/build/manifest
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.2.0 // indirect
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f // indirect
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180718195328-2edc5d4fe051
|
||||
github.com/nicksnyder/go-i18n v1.10.0 // indirect
|
||||
github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3 // indirect
|
||||
github.com/pelletier/go-toml v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.8.0
|
||||
go.uber.org/atomic v1.3.2 // indirect
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
go.uber.org/zap v1.8.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.1 // indirect
|
||||
)
|
30
build/manifest/go.sum
Normal file
30
build/manifest/go.sum
Normal file
|
@ -0,0 +1,30 @@
|
|||
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f h1:t34t/ySFIGsPOLQ/dCcKeCoErlqhXlNLYvPn7mVogzo=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180716205655-f2c180390599 h1:ULtKuAlmCaYC4UfTsGN7BFTGzWPXNmkEtvokk1aSusc=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180716205655-f2c180390599/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180717201910-181fd3dd4d42 h1:dRfBO9L3Q1rjZJN7O1stQrkG/xVqfsi8SCRDwysoFKQ=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180717201910-181fd3dd4d42/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180718195328-2edc5d4fe051 h1:vIs9B718aEEX3ECt9yjKOxIiQKq4KqVIZ5VQIcI08to=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180718195328-2edc5d4fe051/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||
github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q=
|
||||
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
|
||||
github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3 h1:9J0mOv1rXIBlRjQCiAGyx9C3dZZh5uIa3HU0oTV8v1E=
|
||||
github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.8.0 h1:r6Za1Rii8+EGOYRDLvpooNOF6kP3iyDnkpzbw67gCQ8=
|
||||
go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 h1:h7zdf0RiEvWbYBKIx4b+q41xoUVnMmvsGZnIVE5syG8=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
120
build/manifest/main.go
Normal file
120
build/manifest/main.go
Normal file
|
@ -0,0 +1,120 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const PluginIdGoFileTemplate = `package main
|
||||
|
||||
const PluginId = "%s"
|
||||
`
|
||||
|
||||
const PluginIdJsFileTemplate = `export default '%s';
|
||||
`
|
||||
|
||||
func main() {
|
||||
if len(os.Args) <= 1 {
|
||||
panic("no cmd specified")
|
||||
}
|
||||
|
||||
manifest, err := findManifest()
|
||||
if err != nil {
|
||||
panic("failed to find manifest: " + err.Error())
|
||||
}
|
||||
|
||||
cmd := os.Args[1]
|
||||
switch cmd {
|
||||
case "plugin_id":
|
||||
dumpPluginId(manifest)
|
||||
|
||||
case "has_server":
|
||||
if manifest.HasServer() {
|
||||
fmt.Printf("true")
|
||||
}
|
||||
|
||||
case "has_webapp":
|
||||
if manifest.HasWebapp() {
|
||||
fmt.Printf("true")
|
||||
}
|
||||
|
||||
case "apply":
|
||||
if err := applyManifest(manifest); err != nil {
|
||||
panic("failed to apply manifest: " + err.Error())
|
||||
}
|
||||
|
||||
default:
|
||||
panic("unrecognized command: " + cmd)
|
||||
}
|
||||
}
|
||||
|
||||
func findManifest() (*model.Manifest, error) {
|
||||
_, manifestFilePath, err := model.FindManifest(".")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to find manifest in current working directory")
|
||||
}
|
||||
manifestFile, err := os.Open(manifestFilePath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to open %s", manifestFilePath)
|
||||
}
|
||||
defer manifestFile.Close()
|
||||
|
||||
// Re-decode the manifest, disallowing unknown fields. When we write the manifest back out,
|
||||
// we don't want to accidentally clobber anything we won't preserve.
|
||||
var manifest model.Manifest
|
||||
decoder := json.NewDecoder(manifestFile)
|
||||
decoder.DisallowUnknownFields()
|
||||
if err = decoder.Decode(&manifest); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse manifest")
|
||||
}
|
||||
|
||||
return &manifest, nil
|
||||
}
|
||||
|
||||
// dumpPluginId writes the plugin id from the given manifest to standard out
|
||||
func dumpPluginId(manifest *model.Manifest) {
|
||||
fmt.Printf("%s", manifest.Id)
|
||||
}
|
||||
|
||||
// applyManifest propagates the plugin_id into the server and webapp folders, as necessary
|
||||
func applyManifest(manifest *model.Manifest) error {
|
||||
if manifest.HasServer() {
|
||||
if err := ioutil.WriteFile(
|
||||
"server/plugin_id.go",
|
||||
[]byte(fmt.Sprintf(PluginIdGoFileTemplate, manifest.Id)),
|
||||
0644,
|
||||
); err != nil {
|
||||
return errors.Wrap(err, "failed to write server/plugin_id.go")
|
||||
}
|
||||
|
||||
goMod, err := ioutil.ReadFile("server/go.mod")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to read server/go.mod")
|
||||
}
|
||||
|
||||
moduleRe := regexp.MustCompile("module .+")
|
||||
goMod = moduleRe.ReplaceAll(goMod, []byte(fmt.Sprintf("module %s", manifest.Id)))
|
||||
|
||||
if err := ioutil.WriteFile("server/go.mod", goMod, 0644); err != nil {
|
||||
return errors.Wrap(err, "failed to write server/go.mod")
|
||||
}
|
||||
}
|
||||
|
||||
if manifest.HasWebapp() {
|
||||
if err := ioutil.WriteFile(
|
||||
"webapp/src/plugin_id.js",
|
||||
[]byte(fmt.Sprintf(PluginIdJsFileTemplate, manifest.Id)),
|
||||
0644,
|
||||
); err != nil {
|
||||
return errors.Wrap(err, "failed to open webapp/src/plugin_id.js")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
21
plugin.json
Normal file
21
plugin.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"id": "com.mattermost.sample-plugin",
|
||||
"name": "Sample Plugin",
|
||||
"description": "This plugin serves as a starting point for writing a Mattermost plugin.",
|
||||
"version": "0.0.1",
|
||||
"server": {
|
||||
"executables": {
|
||||
"linux-amd64": "server/dist/plugin-linux-amd64",
|
||||
"darwin-amd64": "server/dist/plugin-darwin-amd64",
|
||||
"windows-amd64": "server/dist/plugin-windows-amd64.exe"
|
||||
}
|
||||
},
|
||||
"webapp": {
|
||||
"bundle_path": "webapp/dist/main.js"
|
||||
},
|
||||
"settings_schema": {
|
||||
"header": "",
|
||||
"footer": "",
|
||||
"settings": []
|
||||
}
|
||||
}
|
26
server/go.mod
Normal file
26
server/go.mod
Normal file
|
@ -0,0 +1,26 @@
|
|||
module com.mattermost.sample-plugin
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.1.0 // indirect
|
||||
github.com/gorilla/websocket v1.2.0 // indirect
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f // indirect
|
||||
github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180719183001-d599a74f2cc6
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 // indirect
|
||||
github.com/nicksnyder/go-i18n v1.10.0 // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3 // indirect
|
||||
github.com/pelletier/go-toml v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.8.0 // indirect
|
||||
go.uber.org/atomic v1.3.2 // indirect
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
go.uber.org/zap v1.8.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 // indirect
|
||||
golang.org/x/net v0.0.0-20180712202826-d0887baf81f4 // indirect
|
||||
golang.org/x/text v0.3.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20180716172848-2731d4fa720b // indirect
|
||||
google.golang.org/grpc v1.13.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.1 // indirect
|
||||
)
|
48
server/go.sum
Normal file
48
server/go.sum
Normal file
|
@ -0,0 +1,48 @@
|
|||
github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f h1:t34t/ySFIGsPOLQ/dCcKeCoErlqhXlNLYvPn7mVogzo=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116 h1:Y4V/yReWjQo/Ngyc0w6C3EKXKincp4YgvXeo8lI4LrI=
|
||||
github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180716205655-f2c180390599 h1:ULtKuAlmCaYC4UfTsGN7BFTGzWPXNmkEtvokk1aSusc=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180716205655-f2c180390599/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180719180216-0f672ab36b0e h1:dzS1oPHnRzIQiwHGpN9HrZT825wSXe6tjwuAJ/BRYHc=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180719180216-0f672ab36b0e/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180719183001-d599a74f2cc6 h1:cLxxyKbKCIqkiSPFm2+Kc8KT0k/zLmiie+P0bTPMIB8=
|
||||
github.com/mattermost/mattermost-server v0.0.0-20180719183001-d599a74f2cc6/go.mod h1:5L6MjAec+XXQwMIt791Ganu45GKsSiM+I0tLR9wUj8Y=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q=
|
||||
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3 h1:9J0mOv1rXIBlRjQCiAGyx9C3dZZh5uIa3HU0oTV8v1E=
|
||||
github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.8.0 h1:r6Za1Rii8+EGOYRDLvpooNOF6kP3iyDnkpzbw67gCQ8=
|
||||
go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 h1:h7zdf0RiEvWbYBKIx4b+q41xoUVnMmvsGZnIVE5syG8=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/net v0.0.0-20180712202826-d0887baf81f4 h1:KDF3PK6A+dkI7c4O8QbMtJqcXE3LdNJFGZECIlifQOg=
|
||||
golang.org/x/net v0.0.0-20180712202826-d0887baf81f4/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
google.golang.org/genproto v0.0.0-20180716172848-2731d4fa720b h1:mXqBiicV0B+k8wzFNkKeNBRL7LyRV5xG0s+S6ffLb/E=
|
||||
google.golang.org/genproto v0.0.0-20180716172848-2731d4fa720b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.13.0 h1:bHIbVsCwmvbArgCJmLdgOdHFXlKqTOVjbibbS19cXHc=
|
||||
google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
9
server/main.go
Normal file
9
server/main.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.ClientMain(&Plugin{})
|
||||
}
|
11
server/plugin.go
Normal file
11
server/plugin.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
)
|
||||
|
||||
type Plugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
// See https://developers.mattermost.com/extend/plugins/server/reference/
|
3
server/plugin_id.go
Normal file
3
server/plugin_id.go
Normal file
|
@ -0,0 +1,3 @@
|
|||
package main
|
||||
|
||||
const PluginId = "com.mattermost.sample-plugin"
|
636
webapp/.eslintrc.json
Normal file
636
webapp/.eslintrc.json
Normal file
|
@ -0,0 +1,636 @@
|
|||
{
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"impliedStrict": true,
|
||||
"modules": true,
|
||||
"experimentalObjectRestSpread": true
|
||||
}
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react",
|
||||
"import"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"jquery": true,
|
||||
"es6": true,
|
||||
"jest": true
|
||||
},
|
||||
"globals": {
|
||||
"jest": true,
|
||||
"describe": true,
|
||||
"it": true,
|
||||
"expect": true,
|
||||
"before": true,
|
||||
"after": true,
|
||||
"beforeEach": true
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": "webpack"
|
||||
},
|
||||
"rules": {
|
||||
"array-bracket-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"array-callback-return": 2,
|
||||
"arrow-body-style": 0,
|
||||
"arrow-parens": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"arrow-spacing": [
|
||||
2,
|
||||
{
|
||||
"before": true,
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"block-scoped-var": 2,
|
||||
"brace-style": [
|
||||
2,
|
||||
"1tbs",
|
||||
{
|
||||
"allowSingleLine": false
|
||||
}
|
||||
],
|
||||
"camelcase": [
|
||||
2,
|
||||
{
|
||||
"properties": "never"
|
||||
}
|
||||
],
|
||||
"capitalized-comments": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"comma-dangle": [
|
||||
2,
|
||||
"always-multiline"
|
||||
],
|
||||
"comma-spacing": [
|
||||
2,
|
||||
{
|
||||
"before": false,
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"comma-style": [
|
||||
2,
|
||||
"last"
|
||||
],
|
||||
"complexity": [
|
||||
0,
|
||||
10
|
||||
],
|
||||
"computed-property-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"consistent-return": 2,
|
||||
"consistent-this": [
|
||||
2,
|
||||
"self"
|
||||
],
|
||||
"constructor-super": 2,
|
||||
"curly": [
|
||||
2,
|
||||
"all"
|
||||
],
|
||||
"dot-location": [
|
||||
2,
|
||||
"object"
|
||||
],
|
||||
"dot-notation": 2,
|
||||
"eqeqeq": [
|
||||
2,
|
||||
"smart"
|
||||
],
|
||||
"func-call-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"func-name-matching": 0,
|
||||
"func-names": 2,
|
||||
"func-style": [
|
||||
2,
|
||||
"declaration",
|
||||
{
|
||||
"allowArrowFunctions": true
|
||||
}
|
||||
],
|
||||
"generator-star-spacing": [
|
||||
2,
|
||||
{
|
||||
"before": false,
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"global-require": 2,
|
||||
"guard-for-in": 2,
|
||||
"id-blacklist": 0,
|
||||
"import/no-unresolved": 2,
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"newlines-between": "always-and-inside-groups",
|
||||
"groups": [
|
||||
"builtin",
|
||||
"external",
|
||||
[
|
||||
"internal",
|
||||
"parent"
|
||||
],
|
||||
"sibling",
|
||||
"index"
|
||||
]
|
||||
}
|
||||
],
|
||||
"indent": [
|
||||
2,
|
||||
4,
|
||||
{
|
||||
"SwitchCase": 0
|
||||
}
|
||||
],
|
||||
"jsx-quotes": [
|
||||
2,
|
||||
"prefer-single"
|
||||
],
|
||||
"key-spacing": [
|
||||
2,
|
||||
{
|
||||
"beforeColon": false,
|
||||
"afterColon": true,
|
||||
"mode": "strict"
|
||||
}
|
||||
],
|
||||
"keyword-spacing": [
|
||||
2,
|
||||
{
|
||||
"before": true,
|
||||
"after": true,
|
||||
"overrides": {}
|
||||
}
|
||||
],
|
||||
"line-comment-position": 0,
|
||||
"linebreak-style": 2,
|
||||
"lines-around-comment": [
|
||||
2,
|
||||
{
|
||||
"beforeBlockComment": true,
|
||||
"beforeLineComment": true,
|
||||
"allowBlockStart": true,
|
||||
"allowBlockEnd": true
|
||||
}
|
||||
],
|
||||
"max-lines": [
|
||||
1,
|
||||
{
|
||||
"max": 450,
|
||||
"skipBlankLines": true,
|
||||
"skipComments": false
|
||||
}
|
||||
],
|
||||
"max-nested-callbacks": [
|
||||
2,
|
||||
{
|
||||
"max": 2
|
||||
}
|
||||
],
|
||||
"max-statements-per-line": [
|
||||
2,
|
||||
{
|
||||
"max": 1
|
||||
}
|
||||
],
|
||||
"multiline-ternary": [
|
||||
1,
|
||||
"never"
|
||||
],
|
||||
"new-cap": 2,
|
||||
"new-parens": 2,
|
||||
"newline-before-return": 0,
|
||||
"newline-per-chained-call": 0,
|
||||
"no-alert": 2,
|
||||
"no-array-constructor": 2,
|
||||
"no-await-in-loop": 2,
|
||||
"no-caller": 2,
|
||||
"no-case-declarations": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-compare-neg-zero": 2,
|
||||
"no-cond-assign": [
|
||||
2,
|
||||
"except-parens"
|
||||
],
|
||||
"no-confusing-arrow": 2,
|
||||
"no-console": 2,
|
||||
"no-const-assign": 2,
|
||||
"no-constant-condition": 2,
|
||||
"no-debugger": 2,
|
||||
"no-div-regex": 2,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-class-members": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-duplicate-imports": [
|
||||
2,
|
||||
{
|
||||
"includeExports": true
|
||||
}
|
||||
],
|
||||
"no-else-return": 2,
|
||||
"no-empty": 2,
|
||||
"no-empty-function": 2,
|
||||
"no-empty-pattern": 2,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-label": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-extra-semi": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-global-assign": 2,
|
||||
"no-implicit-coercion": 2,
|
||||
"no-implicit-globals": 0,
|
||||
"no-implied-eval": 2,
|
||||
"no-inner-declarations": 0,
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-labels": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 2,
|
||||
"no-loop-func": 2,
|
||||
"no-magic-numbers": [
|
||||
1,
|
||||
{
|
||||
"ignore": [
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"enforceConst": true,
|
||||
"detectObjects": true
|
||||
}
|
||||
],
|
||||
"no-mixed-operators": [
|
||||
2,
|
||||
{
|
||||
"allowSamePrecedence": false
|
||||
}
|
||||
],
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-assign": 2,
|
||||
"no-multi-spaces": [
|
||||
2,
|
||||
{
|
||||
"exceptions": {
|
||||
"Property": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"no-multi-str": 0,
|
||||
"no-multiple-empty-lines": [
|
||||
2,
|
||||
{
|
||||
"max": 1
|
||||
}
|
||||
],
|
||||
"no-native-reassign": 2,
|
||||
"no-negated-condition": 2,
|
||||
"no-nested-ternary": 2,
|
||||
"no-new": 2,
|
||||
"no-new-func": 2,
|
||||
"no-new-object": 2,
|
||||
"no-new-symbol": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-param-reassign": 2,
|
||||
"no-process-env": 2,
|
||||
"no-process-exit": 2,
|
||||
"no-proto": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-return-assign": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"no-return-await": 2,
|
||||
"no-script-url": 2,
|
||||
"no-self-assign": [
|
||||
2,
|
||||
{
|
||||
"props": true
|
||||
}
|
||||
],
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": [
|
||||
2,
|
||||
{
|
||||
"hoist": "functions"
|
||||
}
|
||||
],
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-tabs": 0,
|
||||
"no-template-curly-in-string": 2,
|
||||
"no-ternary": 0,
|
||||
"no-this-before-super": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-trailing-spaces": [
|
||||
2,
|
||||
{
|
||||
"skipBlankLines": false
|
||||
}
|
||||
],
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 2,
|
||||
"no-underscore-dangle": 2,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unmodified-loop-condition": 2,
|
||||
"no-unneeded-ternary": [
|
||||
2,
|
||||
{
|
||||
"defaultAssignment": false
|
||||
}
|
||||
],
|
||||
"no-unreachable": 2,
|
||||
"no-unsafe-finally": 2,
|
||||
"no-unsafe-negation": 2,
|
||||
"no-unused-expressions": 2,
|
||||
"no-unused-vars": [
|
||||
2,
|
||||
{
|
||||
"vars": "all",
|
||||
"args": "after-used"
|
||||
}
|
||||
],
|
||||
"no-use-before-define": [
|
||||
2,
|
||||
{
|
||||
"classes": false,
|
||||
"functions": false,
|
||||
"variables": false
|
||||
}
|
||||
],
|
||||
"no-useless-computed-key": 2,
|
||||
"no-useless-concat": 2,
|
||||
"no-useless-constructor": 2,
|
||||
"no-useless-escape": 2,
|
||||
"no-useless-rename": 2,
|
||||
"no-useless-return": 2,
|
||||
"no-var": 0,
|
||||
"no-void": 2,
|
||||
"no-warning-comments": 1,
|
||||
"no-whitespace-before-property": 2,
|
||||
"no-with": 2,
|
||||
"object-curly-newline": 0,
|
||||
"object-curly-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"object-property-newline": [
|
||||
2,
|
||||
{
|
||||
"allowMultiplePropertiesPerLine": true
|
||||
}
|
||||
],
|
||||
"object-shorthand": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"one-var": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"one-var-declaration-per-line": 0,
|
||||
"operator-assignment": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"operator-linebreak": [
|
||||
2,
|
||||
"after"
|
||||
],
|
||||
"padded-blocks": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"prefer-arrow-callback": 2,
|
||||
"prefer-const": 2,
|
||||
"prefer-destructuring": 0,
|
||||
"prefer-numeric-literals": 2,
|
||||
"prefer-promise-reject-errors": 2,
|
||||
"prefer-rest-params": 2,
|
||||
"prefer-spread": 2,
|
||||
"prefer-template": 0,
|
||||
"quote-props": [
|
||||
2,
|
||||
"as-needed"
|
||||
],
|
||||
"quotes": [
|
||||
2,
|
||||
"single",
|
||||
"avoid-escape"
|
||||
],
|
||||
"radix": 2,
|
||||
"react/display-name": [
|
||||
0,
|
||||
{
|
||||
"ignoreTranspilerName": false
|
||||
}
|
||||
],
|
||||
"react/forbid-component-props": 0,
|
||||
"react/forbid-elements": [
|
||||
2,
|
||||
{
|
||||
"forbid": [
|
||||
"embed"
|
||||
]
|
||||
}
|
||||
],
|
||||
"react/jsx-boolean-value": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"react/jsx-closing-bracket-location": [
|
||||
2,
|
||||
{
|
||||
"location": "tag-aligned"
|
||||
}
|
||||
],
|
||||
"react/jsx-curly-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"react/jsx-equals-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"react/jsx-filename-extension": 2,
|
||||
"react/jsx-first-prop-new-line": [
|
||||
2,
|
||||
"multiline"
|
||||
],
|
||||
"react/jsx-handler-names": 0,
|
||||
"react/jsx-indent": [
|
||||
2,
|
||||
4
|
||||
],
|
||||
"react/jsx-indent-props": [
|
||||
2,
|
||||
4
|
||||
],
|
||||
"react/jsx-key": 2,
|
||||
"react/jsx-max-props-per-line": [
|
||||
2,
|
||||
{
|
||||
"maximum": 1
|
||||
}
|
||||
],
|
||||
"react/jsx-no-bind": 0,
|
||||
"react/jsx-no-comment-textnodes": 2,
|
||||
"react/jsx-no-duplicate-props": [
|
||||
2,
|
||||
{
|
||||
"ignoreCase": false
|
||||
}
|
||||
],
|
||||
"react/jsx-no-literals": 2,
|
||||
"react/jsx-no-target-blank": 2,
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-pascal-case": 2,
|
||||
"react/jsx-tag-spacing": [
|
||||
2,
|
||||
{
|
||||
"closingSlash": "never",
|
||||
"beforeSelfClosing": "never",
|
||||
"afterOpening": "never"
|
||||
}
|
||||
],
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/jsx-wrap-multilines": 2,
|
||||
"react/no-array-index-key": 1,
|
||||
"react/no-children-prop": 2,
|
||||
"react/no-danger": 0,
|
||||
"react/no-danger-with-children": 2,
|
||||
"react/no-deprecated": 1,
|
||||
"react/no-did-mount-set-state": 2,
|
||||
"react/no-did-update-set-state": 2,
|
||||
"react/no-direct-mutation-state": 2,
|
||||
"react/no-find-dom-node": 1,
|
||||
"react/no-is-mounted": 2,
|
||||
"react/no-multi-comp": [
|
||||
2,
|
||||
{
|
||||
"ignoreStateless": true
|
||||
}
|
||||
],
|
||||
"react/no-render-return-value": 2,
|
||||
"react/no-set-state": 0,
|
||||
"react/no-string-refs": 0,
|
||||
"react/no-unescaped-entities": 2,
|
||||
"react/no-unknown-property": 2,
|
||||
"react/no-unused-prop-types": [
|
||||
1,
|
||||
{
|
||||
"skipShapeProps": true
|
||||
}
|
||||
],
|
||||
"react/prefer-es6-class": 2,
|
||||
"react/prefer-stateless-function": 0,
|
||||
"react/prop-types": [
|
||||
2,
|
||||
{
|
||||
"ignore": [
|
||||
"location",
|
||||
"history",
|
||||
"component"
|
||||
]
|
||||
}
|
||||
],
|
||||
"react/require-default-props": 0,
|
||||
"react/require-optimization": 1,
|
||||
"react/require-render-return": 2,
|
||||
"react/self-closing-comp": 2,
|
||||
"react/sort-comp": 0,
|
||||
"react/style-prop-object": 2,
|
||||
"require-yield": 2,
|
||||
"rest-spread-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"semi": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"semi-spacing": [
|
||||
2,
|
||||
{
|
||||
"before": false,
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"sort-imports": 0,
|
||||
"sort-keys": 0,
|
||||
"space-before-blocks": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"space-before-function-paren": [
|
||||
2,
|
||||
{
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}
|
||||
],
|
||||
"space-in-parens": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [
|
||||
2,
|
||||
{
|
||||
"words": true,
|
||||
"nonwords": false
|
||||
}
|
||||
],
|
||||
"symbol-description": 2,
|
||||
"template-curly-spacing": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"valid-typeof": [
|
||||
2,
|
||||
{
|
||||
"requireStringLiterals": false
|
||||
}
|
||||
],
|
||||
"vars-on-top": 0,
|
||||
"wrap-iife": [
|
||||
2,
|
||||
"outside"
|
||||
],
|
||||
"wrap-regex": 2,
|
||||
"yoda": [
|
||||
2,
|
||||
"never",
|
||||
{
|
||||
"exceptRange": false,
|
||||
"onlyEquality": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
2
webapp/.gitignore
vendored
Normal file
2
webapp/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.npminstall
|
6619
webapp/package-lock.json
generated
Normal file
6619
webapp/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
33
webapp/package.json
Normal file
33
webapp/package.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "webapp",
|
||||
"version": "0.0.1",
|
||||
"description": "This plugin serves as a starting point for writing a Mattermost plugin.",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --mode=production",
|
||||
"lint": "eslint --ignore-pattern node_modules --ignore-pattern dist --ext .js --ext .jsx . --quiet",
|
||||
"fix": "eslint --ignore-pattern node_modules --ignore-pattern dist --ext .js --ext .jsx . --quiet --fix"
|
||||
},
|
||||
"author": "",
|
||||
"license": "",
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.2.6",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"eslint": "^5.2.0",
|
||||
"eslint-import-resolver-webpack": "^0.10.1",
|
||||
"eslint-plugin-import": "^2.13.0",
|
||||
"eslint-plugin-react": "^7.10.0",
|
||||
"webpack": "^4.16.1",
|
||||
"webpack-cli": "^3.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "16.4.1",
|
||||
"react-redux": "5.0.7",
|
||||
"redux": "4.0.0"
|
||||
}
|
||||
}
|
10
webapp/src/index.js
Normal file
10
webapp/src/index.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import PluginId from './plugin_id';
|
||||
|
||||
export default class Plugin {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
initialize(registry, store) {
|
||||
// @see https://developers.mattermost.com/extend/plugins/webapp/reference/
|
||||
}
|
||||
}
|
||||
|
||||
window.registerPlugin(PluginId, new Plugin());
|
1
webapp/src/plugin_id.js
Normal file
1
webapp/src/plugin_id.js
Normal file
|
@ -0,0 +1 @@
|
|||
export default 'com.mattermost.sample-plugin';
|
42
webapp/webpack.config.js
Normal file
42
webapp/webpack.config.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: [
|
||||
'./src/index.js',
|
||||
],
|
||||
resolve: {
|
||||
modules: [
|
||||
'src',
|
||||
'node_modules',
|
||||
],
|
||||
extensions: ['*', '.js', '.jsx'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: ['env', 'react'],
|
||||
plugins: [
|
||||
'transform-class-properties',
|
||||
'transform-object-rest-spread',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
externals: {
|
||||
react: 'React',
|
||||
redux: 'Redux',
|
||||
'react-redux': 'ReactRedux',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, '/dist'),
|
||||
publicPath: '/',
|
||||
filename: 'main.js',
|
||||
},
|
||||
};
|
Reference in a new issue