Menulis aplikasi (plug-in)
Aplikasi menambah ciri ke dalam Antimatter: bahagian pelayan dalam Go yang disambungkan ke pelayan, dan bahagian aplikasi web dalam React yang menambah menu, panel, jenis mesej dan halaman. Halaman ini menunjukkan susunan aplikasi, menggunakan aplikasi Undian yang dibundel sebagai contoh, dan apa yang berubah dalam antara muka Fusion Antimatter.
Cara aplikasi berfungsi
- Bahagian pelayan ialah program Go. Pelayan memulakannya sebagai proses berasingan dan berinteraksi dengannya melalui RPC: ia memanggil hook aplikasi (mesej akan diposkan, arahan dijalankan…), dan aplikasi memanggil API plug-in pelayan (mencipta pos, membaca pengguna, menyimpan data…). Ia juga boleh menyediakan laluan HTTP di bawah
/plugins/<app id>/. - Bahagian aplikasi web ialah bundle JavaScript yang dimuat ke pelayar bersama aplikasi web. Ia mendaftarkan komponen React dan callback dengan registri: butang dalam menu, panel, cara untuk melukis jenis mesej.
- Mana-mana bahagian adalah pilihan. Aplikasi dipasang sebagai bundle
.tar.gz, dan pentadbir sistem membolehkan, melumpuhkan dan mengkonfigurasikannya.
Antimatter menjalankan aplikasi yang ditulis untuk Mattermost, dan sebaliknya, selagi aplikasi hanya menggunakan hook yang dimiliki oleh kedua-duanya. Lihat Hook yang hanya dimiliki oleh Antimatter.
Susunan bundle
Tiada templat pemula berasingan: mulakan daripada aplikasi bundel kecil seperti antimatter-plugin-polls atau antimatter-plugin-todo, dan ubah ID serta kodnya. Undian disusun seperti ini:
antimatter-plugin-polls/
├── plugin.json the manifest
├── Makefile build, test, bundle, deploy
├── build/ the manifest and pluginctl helper tools (Go), setup.mk
├── assets/icon.svg files shipped with the bundle
├── go.mod
├── server/
│ ├── main.go plugin.ClientMain(&Plugin{})
│ ├── plugin.go the Plugin type, OnActivate, ServeHTTP
│ ├── manifest.go generated from plugin.json
│ ├── api.go, command.go, hooks.go, store.go …
│ └── dist/ compiled binaries, one per platform
└── webapp/
├── package.json, webpack.config.js, tsconfig.json
├── i18n/ en.json and one file per language
├── src/index.tsx registers the app with the web app
├── src/manifest.ts generated from plugin.json
├── src/translations.ts
└── dist/main.js the bundle
Pilihan: folder public/, dilayani seperti apa adanya di /plugins/<app id>/public/.
plugin.json
{
"id": "com.example.weather",
"name": "Weather",
"description": "Forecasts in the chat.",
"homepage_url": "https://github.com/example/weather",
"support_url": "https://github.com/example/weather/issues",
"icon_path": "assets/icon.svg",
"version": "1.0.0",
"min_server_version": "12.0.0",
"server": {
"executables": {
"linux-amd64": "server/dist/plugin-linux-amd64",
"linux-arm64": "server/dist/plugin-linux-arm64",
"darwin-amd64": "server/dist/plugin-darwin-amd64",
"darwin-arm64": "server/dist/plugin-darwin-arm64",
"windows-amd64": "server/dist/plugin-windows-amd64.exe"
}
},
"webapp": {"bundle_path": "webapp/dist/main.js"},
"settings_schema": {"settings": []}
}
id: unik dan kekal; nama domain terbalik adalah biasa. Ia menamakan laluan, tetapan yang disimpan dan peristiwa WebSocket.version: versi semantik. Aplikasi bundel tidak menyertainya dalamplugin.json; alat pembinaannya mengambilnya daripada tag gitv*terkini.min_server_version: Antimatter melaporkan12.0.0.settings_schema: halaman tetapan aplikasi dalam Konsol Sistem (lihat Tetapan).
make apply menyalin manifest ke server/manifest.go dan webapp/src/manifest.ts; make manifest-check memvalidasinya.
Bahagian pelayan
Bahagian pelayan mengimport modul Go yang sama seperti aplikasi Mattermost, github.com/mattermost/mattermost/server/public, dari proksi modul Go. main miliknya hanya memulakan aplikasi:
package main
import "github.com/mattermost/mattermost/server/public/plugin"
func main() {
plugin.ClientMain(&Plugin{})
}
Jenis Plugin membenamkan plugin.MattermostPlugin, yang memberikannya p.API, dan melaksanakan hook yang diperlukan:
type Plugin struct {
plugin.MattermostPlugin
router *mux.Router
}
func (p *Plugin) OnActivate() error {
p.router = p.newRouter()
return p.API.RegisterCommand(&model.Command{
Trigger: "weather",
AutoComplete: true,
AutoCompleteDesc: "Show the forecast",
AutoCompleteHint: "[city]",
})
}
func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
city := strings.TrimSpace(strings.TrimPrefix(args.Command, "/weather"))
return &model.CommandResponse{
ResponseType: model.CommandResponseTypeEphemeral,
Text: "Forecast for " + city + ": sunny",
}, nil
}
func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
p.router.ServeHTTP(w, r)
}
Hook biasa
| Hook | Bila ia dilaksanakan |
|---|---|
OnActivate, OnDeactivate | Bila aplikasi diaktifkan atau dinyahaktifkan, dan bila pelayan bermula dan berhenti. Daftarkan arahan dan bot dalam OnActivate. |
OnConfigurationChange | Bila tetapan berubah; muatkannya dengan p.API.LoadPluginConfiguration(&cfg). |
ServeHTTP | Permintaan ke /plugins/<app id>/…. Pelayan menetapkan pengepala Mattermost-User-Id bila permintaan datang daripada pengguna yang log masuk; tolak permintaan tanpa pengepala ini melainkan ia dimaksudkan untuk awam. |
ExecuteCommand | Arahan yang didaftarkan oleh aplikasi telah dilaksanakan. |
MessageWillBePosted, MessageWillBeUpdated | Sebelum mesej disimpan: kembalikan hantaran yang diubah, atau sebab untuk menolaknya. |
MessageHasBeenPosted, MessageHasBeenUpdated, MessageHasBeenDeleted | Selepas kejadian, untuk kesan sampingan. |
ReactionHasBeenAdded, ReactionHasBeenRemoved | Reaksi. |
UserHasJoinedChannel, UserHasLeftChannel, UserHasJoinedTeam, UserHasLeftTeam, ChannelHasBeenCreated | Keahlian dan perubahan saluran. Pasukan ialah komuniti. |
FileWillBeUploaded | Sebelum fail disimpan: ubah atau tolak. |
OnPluginClusterEvent | Mesej daripada aplikasi yang sama pada pelayan lain dalam kluster. |
Senarai penuh, dengan tanda tangan yang tepat, ada dalam server/public/plugin/hooks.go; API ada dalam server/public/plugin/api.go. Pakej pluginapi (server/public/pluginapi) membungkus API dalam pembantu yang lebih mesra.
Panggilan API berguna
CreatePost,UpdatePost,SendEphemeralPost: hantar sebagai bot aplikasi atau sebagai pengguna.EnsureBotUser(&model.Bot{Username, DisplayName}): cipta bot aplikasi sekali dan dapatkan ID-nya.PublishWebSocketEvent("poll_updated", payload, &model.WebsocketBroadcast{ChannelId: id}): hantar peristiwa ke aplikasi web. Ia tiba sebagaicustom_<app id>_poll_updated.OpenInteractiveDialog: buka dialog.LogInfo,LogErrordan rakan-rakan: tulis ke log pelayan, ditanda dengan ID aplikasi.GetUser,GetChannel,HasPermissionToChannel: semak siapa yang boleh melakukan apa sebelum bertindak untuk pengguna.
Aplikasi ini berjalan pada setiap pelayan dalam kluster. Simpan keadaan dalam stor kunci-nilai atau pangkalan data, bukan hanya dalam memori.
Perkhidmatan AI
Pelayan Antimatter memanggil model AI untuk aplikasi, melalui sambungan model yang diset oleh pentadbir (lihat AI dalam panduan pentadbiran). Aplikasi tidak pernah memegang kunci penderma: ia hanya menyatakan nama individu yang dilayan dan lokasinya, dan pelayan akan memeriksa sama ada individu tersebut dibenarkan menggunakan sambungan di situ, mengenakan had dan belanjanya, mengira token terhadap individu dan aplikasi tersebut, serta mengaudit panggilan tanpa mengandungi isinya.
| Kaedah | Fungsinya |
|---|---|
AIChat(actingUserID, channelID, teamID, *ai.ChatRequest) | Penyempurnaan sembang: mesej, alat, keluaran berstruktur (JSONSchema). |
AIChatStream(…) | Sama, tetapi dalam aliran: baca Events aliran sehingga saluran ditutup, atau Close untuk menghentikan panggilan. |
AIEmbed(…, *ai.EmbedRequest) | Penyematan teks. |
AITranscribe(…, *ai.TranscribeRequest) | Suara ke teks. |
AIDecide(…, *ai.DecideRequest) | Soalan bertip kepada model keputusan (ya atau tidak, pilihan, skor) tentang sesuatu teks. |
AIConnectionsForUser(userID, channelID, teamID) | Sambungan yang boleh digunakan oleh seseorang di situ, dengan model dan keupayaannya, tetapi tidak pernah kuncinya. |
ConnectionID bagi setiap permintaan memilih sambungan, dan Model memilih salah satu modelnya (kosong untuk lalai sambungan). Operation ialah label ringkas untuk rekod penggunaan dan audit, bukan isinya. Versi pelayan minimumnya ialah 11.11.
actingUserID hanya daripada sumber yang disahkan oleh pelayan: pengepala Mattermost-User-Id bagi permintaan kepada ServeHTTP anda, atau pengguna dalam konteks hook (pengarang hantaran, pengguna yang menjalankan arahan). Jangan pernah ambillah daripada mesej, muatan webhook, URL atau permintaan aplikasi lain: aplikasi anda akan menggunakan akses orang lain.Kaedah ini dan pakej ai (server/public/ai) wujud hanya dalam salinan modul Antimatter, bukan dalam versi yang diterbitkan oleh Mattermost. Untuk menggunakannya, bina terhadap server/public Antimatter dengan baris replace dalam go.mod anda, sebagai contoh replace github.com/mattermost/mattermost/server/public => ../antimatter/server/public. Aplikasi sedemikian hanya akan berjalan di Antimatter.
Menyimpan data
Setiap aplikasi mempunyai stor kunci-nilai miliknya sendiri dalam pangkalan data pelayan:
KVSet(key, value),KVGet(key),KVDelete(key): nilai adalah dalam bentuk pita (bytes), biasanya JSON. Kunci adalah paling banyak 150 aksara.KVSetWithExpiry(key, value, seconds): nilai akan hilang selepas tempoh masa tersebut.KVCompareAndSet(key, old, new)danKVSetWithOptionsdenganAtomic: kemas kini yang selamat apabila beberapa permintaan atau pelayan menulis ke kunci yang sama. Undian menyimpan setiap undian dengan cara ini dan mencuba semula jika berlaku percanggahan.KVList(page, perPage): kunci, halaman demi halaman.
Bahagian aplikasi web
Bundel (bundle) mendaftar kelas dengan window.registerPlugin. Metod initialize miliknya menerima registri dan stor Redux:
import manifest from './manifest';
class Plugin {
initialize(registry, store) {
registry.registerTranslations((locale) => translationsFor(locale));
registry.registerPostTypeComponent('custom_poll', PollPost);
registry.registerWebSocketEventHandler(`custom_${manifest.id}_poll_updated`, (msg) => {
store.dispatch(pollUpdated(JSON.parse(msg.data.poll)));
});
registry.registerReconnectHandler(() => store.dispatch(reloadPolls()));
}
}
window.registerPlugin(manifest.id, new Plugin());
- Pustaka bersama. Aplikasi web menyediakan React, ReactDOM, Redux, React Redux dan React Intl: senaraikan sebagai
externalswebpack (React,ReactDOM,Redux,ReactRedux,ReactIntl) bukannya membundel salinan anda sendiri. Lihatwebpack.config.jsUndian. - Memanggil bahagian pelayan anda. Ambil (fetch)
${window.basename}/plugins/<app id>/…dengan pilihan daripadaClient4.getOptions()(daripadamattermost-redux/client): ia membawa pengepala (headers) yang diperlukan oleh pelayan untuk menerima permintaan daripada pelayar. - Keadaan anda sendiri.
registerReducermenambah reducer, disimpan di bawahstate['plugins-<app id>']. - Jenis (Types). Kaedah registri tambahan Antimatter tidak terdapat dalam jenis yang diterbitkan oleh Mattermost: Undian menyatakan registri yang digunakan dalam
webapp/src/types/host.ts.
Kaedah registri dan parameternya didokumentasikan dalam kod, dalam webapp/fusion/src/plugins/registry.ts (Fusion) dan webapp/channels/src/plugins/registry.ts (klasik).
Menyokong antara muka Fusion
Antimatter mempunyai dua antara muka web: Fusion, yang lalai, dan yang klasik. Kedua-duanya memuatkan bundel aplikasi yang sama dan mempunyai registri yang sama, tetapi Fusion melukis banyak perkara sendiri dan meletakkan komponen plugin dengan caranya sendiri. Ujikan aplikasi anda dalam kedua-duanya.
Mengesan antara muka
Sebelum mana-mana aplikasi dimuatkan, kedua-dua antara muka menetapkan window.antimatterWebUI kepada 'fusion' atau 'classic', dan nilai yang sama pada elemen akar halaman sebagai data-am-web-ui. Pada Mattermost, tiada satu pun ditetapkan.
export function isFusionUI(): boolean {
return window.antimatterWebUI === 'fusion' || document.documentElement.dataset.amWebUi === 'fusion';
}
Aplikasi terikat menggunakan ini untuk melukis dengan cara yang berbeza. Undian melukis kad undian dan dialog penciptaannya dalam gaya Fusion, dan membuka dialognya sendiri untuk /poll dalam Fusion. Panggilan dan Saluran Suara meninggalkan komponen bar sisi dan toast yang digantikan oleh Fusion dengan antara muka panggilannya sendiri. Aplikasi Ejen meletakkan tindakan AI-nya dalam menu mesej, sebagai kumpulan di bawah Lagi Tindakan, bukannya bar alat hover. Kelas CSS Fusion sendiri (dihubungkan dengan am-) dan lapisan dialognya (elemen am-layer) adalah apa yang digunakan oleh aplikasi ini untuk memadankan antara muka; ia bukan API yang didokumentasikan dan stabil.
Di mana Fusion menunjukkan komponen plugin
| Kaedah registri | Di mana ia muncul dalam Fusion |
|---|---|
registerAppBarComponent, registerChannelHeaderButtonAction | Rel aplikasi, lajur ikon di hujung kanan, antara avatar anda dan butang Tentang Antimatter. Butang pengepal saluran juga pergi ke sana, bukan dalam pengepal saluran. Disembunyikan apabila pentadbir sistem menghidupkan Matikan Bar Aplikasi (ExperimentalSettings.DisableAppBar, luar secara lalai). |
registerRightHandSidebarComponent | Panel sebelah kanan. Orang boleh mengubah saiznya dengan menarik tepinya, dan membukanya dalam tetingkap baharu. Jika aplikasi itu juga merupakan produk, panel menawarkan Buka sebagai halaman penuh. Lihat Panel dalam tetingkap baharu. |
registerChannelHeaderIcon | Ikon dalam pengepal saluran, selepas butang panggilan; pada telefon, dalam menu Lagi pengepal. |
registerCallButtonAction | Butang panggilan pengepal saluran; beberapa penyedia berkongsi menu Cara lain untuk membuat panggilan. |
registerPostDropdownMenuAction | Menu Aksi mesej (⋯) mesej, dalam submenunya Lagi Tindakan; juga dalam menu Tindakan bebenang panel bebenang, di bawah Lagi Tindakan. Fusion melukis ikon aplikasi sebelum setiap tindakan, dalam kelabu: ikonnya sendiri untuk aplikasi terikat, jika tidak ikon yang dipaparkan oleh aplikasi dalam rel aplikasi, jika tidak yang neutral. Elemen tanpa teks di awal teks tindakan (ikon yang dilukis oleh aplikasi itu sendiri) disembunyikan. |
registerPostDropdownSubMenuAction | Kumpulan dengan tajuk dalam submenunya Lagi Tindakan yang sama, selepas tindakan tunggal. Tiada aplikasi mendapat entri miliknya sendiri dalam menu mesej. |
registerPostActionComponent | Bar alat hover mesej, sebelum butang ⋯. |
registerPostTypeComponent, registerPostMessageAttachmentComponent, registerPostHeaderComponent, registerPostWillRenderEmbedComponent | Mesej itu sendiri: badannya, di bawah teksnya, selepas masanya, dan di tempat pratonton pautan. |
registerChannelHeaderMenuAction | Menu Pilihan saluran saluran (⋯ pada saluran dalam bar sisi, atau klik kanan), sebagai item dengan ikon palam. |
registerMainMenuAction | Menu komuniti (nama komuniti di bahagian atas senarai saluran), di bawah Lagi Tindakan, dikelompokkan mengikut aplikasi. |
registerSidebarBrowseOrAddChannelMenuAction | Menu komuniti, selepas Cipta saluran dan Cipta kategori. |
registerFileUploadMethod | Menu + komposer (Tambah pada mesej), selepas Muat naik fail. |
registerPostEditorActionComponent | Bar format komposer, apabila format dipaparkan. |
registerAIActionMenuItemComponent | Menu AI komposer. |
registerFileDropdownMenuAction, registerFilePreviewComponent | Menu pilihan fail, dan pratonton fail. |
registerUserSettings | Profil & tetapan, satu tab setiap aplikasi di bawah tajuk Plugin. |
registerChannelSettingsTab | Dialog tetapan saluran, di bawah tajuk Aplikasi. |
registerPopoverUserAttributesComponent, registerPopoverUserActionsComponent | Kad profil yang dipaparkan apabila anda mengklik nama atau avatar. |
registerLeftSidebarHeaderComponent, registerSidebarChannelLinkLabelComponent, registerChannelIconOverride, registerBottomTeamSidebarComponent | Bahagian atas senarai saluran komuniti, di sebelah nama saluran, ikon saluran, dan bahagian bawah rel komuniti di sebelah kiri. |
registerChannelIntro, registerChannelIntroButtonAction, registerChannelToastComponent, registerNewMessagesSeparatorActionComponent, registerChannelComposerBannerComponent, registerComposerPlaceholder | Mula-mula sejarah saluran, bahagian atas senarai mesej, garisan belum dibaca, di atas komposer, dan pemegang tempat komposer. |
registerChannelTypeOption | Jenis-jenis saluran dalam dialog Cipta saluran. |
registerSearchComponents | Kotak carian dalam pengepal saluran: skop aplikasi muncul apabila ia kosong. |
registerUserGuideDropdownMenuAction | Tentang Antimatter (bahagian bawah rel aplikasi), di bawah Bantuan. |
registerProduct | Halaman penuh pada URL produk, disenaraikan di bawah Produk dalam Tentang Antimatter. Halaman produk mengekalkan bingkai halaman klasik, yang menu produknya hanya dipaparkan apabila aplikasi mendaftar produk atau menambah entri ke dalamnya. Aplikasi Kanban dan Buku Taktik terikat tidak lagi mendaftar produk: halaman mereka dibuka dalam panel sisi mereka. |
registerRootComponent, registerGlobalComponent, hook seperti registerMessageWillBePostedHook, registerSlashCommandWillBePostedHook, registerMessageWillFormatHook, registerFilesWillUploadHook, registerDesktopNotificationHook, registerWebSocketEventHandler, registerReducer, registerTranslations | Berfungsi seperti dalam antara muka klasik. |
registerAdminConsolePlugin, registerAdminConsoleCustomSetting | Konsol Sistem, yang merupakan versi klasik dalam kedua-dua antara muka. |
Apa yang tidak dipaparkan atau dijalankan oleh Fusion
registerPostDropdownMenuComponent(komponen dalam menu mesej),registerPostCardTypeComponent(kad mesej dalam panel kanan) danregisterProductSwitcherMenuItemtidak dipaparkan dalam pandangan utama Fusion. GunaregisterPostDropdownMenuActionsebagai ganti yang pertama.registerMessageWillBeUpdatedHooktidak dijalankan apabila mesej disunting dalam Fusion. Periksa pindaan pada pelayan dengan hookMessageWillBeUpdatedsebagai gantinya.registerActionAfterChannelCreationhanya dijalankan dari dialog penciptaan saluran klasik, yang dibuka oleh Fusion dari Pilihan lain… dalam dialog Cipta salurannya.- Komponen bar aplikasi dipaparkan tanpa mengira
supportedProductIdsmereka. - Laluan dari
registerNeedsTeamRoutedanregisterCustomRoutemengekalkan bingkai laman klasik, seperti produk.
Hook yang hanya ada pada Antimatter
Kaedah registri ini tidak wujud pada Mattermost. Pastikan kaedah wujud sebelum dipanggil, supaya aplikasi juga berfungsi di sana:
if (typeof registry.registerComposerMenuItem === 'function') {
registry.registerComposerMenuItem({
text: 'Create a poll',
icon: <i className='icon icon-chart-bar'/>,
fusionIcon: 'poll',
action: ({channelId, rootId}) => openPollCreation(channelId, rootId),
});
} else {
registry.registerChannelHeaderButtonAction(icon, (channel) => openPollCreation(channel.id), 'Create a poll', 'Create a poll');
}
| Kaedah | Apa yang ditambah |
|---|---|
registerComposerMenuItem({text, icon, fusionIcon, action, shouldRender}) | Item dalam menu + kotak mesej, dalam kedua-dua antara muka. action menerima {channelId, rootId}. |
registerEmojiPickerTab({id, label, icon, fusionIcon, order, component, shouldRender, replacesGifPicker}) | Tab pemilih emoji kotak mesej, seperti GIF atau pelekat. Dalam Fusion, tab dengan order di bawah 10 datang sebelum tab Emoji. Komponen menerima channelId, rootId, filter, onFilterChange, onSelectDone, insertText, isFusion dan, dalam Fusion, pickerKit (lihat di bawah). |
registerChannelViewPanel({matcher, component}) | Panel antara pengepala saluran dan mesej, untuk saluran yang dipilih oleh matcher(state, channel). Ia boleh menyembunyikan mesej dan komposer (setMessagesVisible), seperti yang dilakukan oleh saluran suara. |
registerSidebarChannelFooterComponent(component) | Baris di bawah saluran dalam bar sisi, seperti orang-orang dalam panggilannya. Ia menerima channel. |
registerIntegrationsOption({title, description, fusionIcon, action, shouldRender}) | Khusus Fusion: entri pada halaman Integrasi, bersebelahan emoji tersuai. Aplikasi GIF menambah GIF dan pelekat tersuainya di sana. |
Tambah dan urus paparan dalam pemilih emoji
Dalam Fusion, tab pemilih emoji menerima prop pickerKit: komponen yang digunakan oleh tab Emoji untuk paparan tambah dan urusannya sendiri, supaya paparan tab kelihatan sama dan kekal di dalam pemilih. Aplikasi GIF dan Memes menggunakannya untuk menambah dan mengurus GIF, pelekat dan templat meme. Ia mengandungi version (1), hook usePickerView dan useOnEscape, serta komponen PickerViewButtons (butang + dan urus di sebelah kotak carian), PickerViewFrame (paparan dengan anak panah belakang), PickerNotice, PickerField, PickerSearch, PickerDropZone dan PickerManageList. Tekan Escape untuk kembali dari paparan ke grid tab. Semak bahawa prop ini wujud: hos lain tidak menyertainya, dan tab akan mengekalkan dialognya sendiri. Jenisnya terdapat dalam webapp/fusion/src/types/store/plugins.ts (EmojiPickerTabProps) dan komponennya dalam webapp/fusion/src/fusion/popovers/picker_views.tsx.
Panel dalam tetingkap baharu
Fusion memberikan dua prop tambahan kepada komponen registerRightHandSidebarComponent, supaya Buka dalam tetingkap baharu membuka panel di tempat asalnya dan bukan di halaman utama aplikasi:
setPanelState(state): panggil apabila panel berubah tempat, dengan rentetan pendek yang ditakrifkan oleh aplikasi anda, seperti'note/<id>'atau'board/<id>/card/<id>', ataunulldi halaman utamanya. Ia akan diletakkan dalam alamat tetingkap, jadi jangan letakkan rahsia di dalamnya. Jika keadaan melebihi 512 aksara atau mengandungi aksara kawalan, ia akan dibuang.initialPanelState: dalam tetingkap baharu, keadaan yang dimiliki oleh panel, atauundefined. Anggap ia sebagai input yang tidak dipercayai: dapatkan semula item sebagai pengguna yang log masuk, dan tampilkan halaman utama aplikasi atau paparan tidak ditemui jika mereka tidak dapat membukanya.
Keadaan ini dilupakan apabila panel ditutup atau panel aplikasi lain mengambil tempatnya. Untuk membuka tetingkap panel anda sendiri, popoutRhsPlugin (juga dalam window.WebappUtils.popouts) menerima keadaan sebagai hujah kelima yang pilihan. Nota, Papan Putih, Senarai tugasan, Kanban dan Buku Taktik menggunakan ini.
fusionIcon menamakan ikon daripada set ikon Fusion (contohnya poll, sticker, calendar atau image; lihat webapp/fusion/src/fusion/components/icon). Fusion memaparkannya sebagai ganti icon, supaya item tersebut sepadan dengan yang lain.
Tetapan
settings_schema dalam plugin.json menerangkan halaman aplikasi dalam Konsol Sistem › Plugin:
"settings_schema": {
"header": "Forecasts come from the weather service below.",
"settings": [
{"key": "ServiceURL", "display_name": "Service URL", "type": "text", "default": "https://api.example.com"},
{"key": "Units", "display_name": "Units", "type": "dropdown", "default": "metric",
"options": [{"display_name": "Celsius", "value": "metric"}, {"display_name": "Fahrenheit", "value": "imperial"}]},
{"key": "EnableAlerts", "display_name": "Severe weather alerts", "type": "bool", "default": false,
"help_text": "Post alerts in the channels that follow a city."}
]
}
Jenis tetapan: bool, text, longtext, number, dropdown, radio, generated (rahsia rawak), username, dan custom (dilukis oleh komponen yang didaftarkan oleh bahagian aplikasi web dengan registerAdminConsoleCustomSetting). Tetapan boleh dikelompokkan dalam sections.
Bahagian pelayan membacanya ke dalam struktur yang medan-medannya sepadan dengan kunci-kunci:
type configuration struct {
ServiceURL string
Units string
EnableAlerts bool
}
func (p *Plugin) OnConfigurationChange() error {
var cfg configuration
if err := p.API.LoadPluginConfiguration(&cfg); err != nil {
return err
}
p.setConfiguration(&cfg)
return nil
}
Pentadbir juga boleh menetapkannya dalam konfigurasi, di bawah PluginSettings.Plugins.<app id>, dengan kunci dalam huruf kecil (lihat panduan pentadbir).
Terjemahan
Antimatter diterjemahkan ke dalam 37 bahasa, dan aplikasi yang dibundel juga. Bahagian aplikasi web melakukannya seperti ini:
- Tulis setiap string dengan React Intl, dengan ID dan teks Inggerisnya:
<FormattedMessage id='polls.create' defaultMessage='Create a poll'/>ataudefineMessages. Letakkan nama aplikasi anda sebagai awalan untuk ID. - Ekstrak string Inggeris ke dalam
webapp/i18n/en.json(aplikasi yang dibundel menggunakanformatjs extract). - Tambahkan satu fail untuk setiap bahasa di sebelahnya, dengan ID yang sama:
fr.json,de.json,pt-BR.json,zh-CN.json… - Beri kepada aplikasi web, yang meminta bahasa pengguna:
import fr from '../i18n/fr.json'; import ptBR from '../i18n/pt-BR.json'; const catalogs = {fr, 'pt-BR': ptBR}; export function translationsFor(locale) { return catalogs[locale] || catalogs[locale.split('-')[0]] || {}; } registry.registerTranslations(translationsFor);
Jika rantaian tidak wujud, ia akan kembali kepada defaultMessage dalam bahasa Inggeris. Bagi rantaian yang dihantar oleh bahagian pelayan (jawapan arahan, mesej bot), pakej pluginapi/i18n memuat fail terjemahan yang dibekalkan dalam bundle (contohnya assets/i18n) dan memberikan pelokalisator dalam bahasa setiap pengguna.
Bina, pasang dan debug
Anda perlukan Go dan Node.js (versi dalam .nvmrc aplikasi). Dalam folder aplikasi:
| Arahan | Fungsinya |
|---|---|
make dist | Membina bahagian pelayan untuk setiap platform dan bahagian aplikasi web, serta menulis bundle ke dist/<app id>-<version>.tar.gz. |
make test | Menjalankan ujian Go dan JavaScript. |
make check-style | Menyemak kod (golangci-lint, ESLint) dan memeriksa jenis TypeScript. |
make deploy | Membina, kemudian memasang dan membolehkan bundle pada pelayan. |
make watch, make deploy-from-watch | Yang pertama membina bahagian aplikasi web setiap kali anda menyimpan; yang kedua membundel apa yang dibina dan memasangnya pada pelayan. |
make enable, make disable, make reset | Membolehkan, melumpuhkan, atau memulakan semula aplikasi pada pelayan. |
make logs, make logs-watch | Menunjukkan baris aplikasi dalam log pelayan. |
make attach | Melekatkan pengembug Delve pada bahagian pelayan yang sedang berjalan (bina dengan AM_DEBUG=1 terlebih dahulu). |
make deploy dan arahan pelayan lain menggunakan soket mod tempatan apabila menemuinya (/var/tmp/antimatter_local.socket, atau AM_LOCALSOCKETPATH): jalankan pada mesin pelayan dengan mod tempatan dihidupkan. Jika tidak, ia akan log masuk ke pelayan yang diberikan oleh MM_SERVICESETTINGS_SITEURL menggunakan AM_ADMIN_TOKEN, atau AM_ADMIN_USERNAME dan AM_ADMIN_PASSWORD. Alat bina belum membaca nama AM_ untuk URL laman web.
Pasang bundle secara manual
- Pentadbir sistem membenarkan muat naik dengan
AM_PLUGINSETTINGS_ENABLEUPLOADS=true(lumpuh secara lalai; tiada suis Konsol Sistem). - Kemudian Konsol Sistem › Plugin › Pengurusan Plagin › Muat Naik Plagin, atau
amctl plugin add weather.tar.gzdiikuti denganamctl plugin enable com.example.weather. - Jika pelayan mempunyai Wajibkan Tandatangan Plugin dihidupkan, ia hanya menerima bundle yang ditandatangani dengan kunci yang dipercayainya; lihat Memasang aplikasi lain.
AM_SERVICESETTINGS_ENABLEDEVELOPER=true pada pelayan: ralat kemudian membawa butiran. Fail Make aplikasi terbenam membina bahagian pelayan untuk platform anda sahaja apabila MM_SERVICESETTINGS_ENABLEDEVELOPER ditetapkan dalam shell anda.