AppContainer.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import { Container } from 'unstated';
  2. import GrowiRenderer from '../util/GrowiRenderer';
  3. import { i18nFactory } from '../util/i18n';
  4. /**
  5. * Service container related to options for Application
  6. * @extends {Container} unstated Container
  7. */
  8. export default class AppContainer extends Container {
  9. constructor() {
  10. super();
  11. // get csrf token from body element
  12. // DO NOT REMOVE: uploading attachment data requires appContainer.csrfToken
  13. const body = document.querySelector('body');
  14. this.csrfToken = body.dataset.csrftoken;
  15. this.config = JSON.parse(document.getElementById('growi-context-hydrate').textContent || '{}');
  16. const currentUserElem = document.getElementById('growi-current-user');
  17. if (currentUserElem != null) {
  18. this.currentUser = JSON.parse(currentUserElem.textContent);
  19. }
  20. const userLocaleId = this.currentUser?.lang;
  21. this.i18n = i18nFactory(userLocaleId);
  22. this.containerInstances = {};
  23. this.componentInstances = {};
  24. this.rendererInstances = {};
  25. }
  26. /**
  27. * Workaround for the mangling in production build to break constructor.name
  28. */
  29. static getClassName() {
  30. return 'AppContainer';
  31. }
  32. initApp() {
  33. this.injectToWindow();
  34. }
  35. initContents() {
  36. const body = document.querySelector('body');
  37. this.isDocSaved = true;
  38. this.originRenderer = new GrowiRenderer(this);
  39. const isPluginEnabled = body.dataset.pluginEnabled === 'true';
  40. if (isPluginEnabled) {
  41. this.initPlugins();
  42. }
  43. this.injectToWindow();
  44. }
  45. initPlugins() {
  46. const growiPlugin = window.growiPlugin;
  47. growiPlugin.installAll(this, this.originRenderer);
  48. }
  49. injectToWindow() {
  50. window.appContainer = this;
  51. const originRenderer = this.getOriginRenderer();
  52. window.growiRenderer = originRenderer;
  53. // backward compatibility
  54. window.crowi = this;
  55. window.crowiRenderer = originRenderer;
  56. window.crowiPlugin = window.growiPlugin;
  57. }
  58. get currentUserId() {
  59. if (this.currentUser == null) {
  60. return null;
  61. }
  62. return this.currentUser._id;
  63. }
  64. get currentUsername() {
  65. if (this.currentUser == null) {
  66. return null;
  67. }
  68. return this.currentUser.username;
  69. }
  70. getConfig() {
  71. return this.config;
  72. }
  73. /**
  74. * Register unstated container instance
  75. * @param {object} instance unstated container instance
  76. */
  77. registerContainer(instance) {
  78. if (instance == null) {
  79. throw new Error('The specified instance must not be null');
  80. }
  81. const className = instance.constructor.getClassName();
  82. if (this.containerInstances[className] != null) {
  83. throw new Error('The specified instance couldn\'t register because the same type object has already been registered');
  84. }
  85. this.containerInstances[className] = instance;
  86. }
  87. /**
  88. * Get registered unstated container instance
  89. * !! THIS METHOD SHOULD ONLY BE USED FROM unstated CONTAINERS !!
  90. * !! From component instances, inject containers with `import { Subscribe } from 'unstated'` !!
  91. *
  92. * @param {string} className
  93. */
  94. getContainer(className) {
  95. return this.containerInstances[className];
  96. }
  97. /**
  98. * Register React component instance
  99. * @param {string} id
  100. * @param {object} instance React component instance
  101. */
  102. registerComponentInstance(id, instance) {
  103. if (instance == null) {
  104. throw new Error('The specified instance must not be null');
  105. }
  106. this.componentInstances[id] = instance;
  107. }
  108. /**
  109. * Get registered React component instance
  110. * @param {string} id
  111. */
  112. getComponentInstance(id) {
  113. return this.componentInstances[id];
  114. }
  115. getOriginRenderer() {
  116. return this.originRenderer;
  117. }
  118. /**
  119. * factory method
  120. */
  121. getRenderer(mode) {
  122. if (this.rendererInstances[mode] != null) {
  123. return this.rendererInstances[mode];
  124. }
  125. const renderer = new GrowiRenderer(this, this.originRenderer);
  126. // setup
  127. renderer.initMarkdownItConfigurers(mode);
  128. renderer.setup(mode);
  129. // register
  130. this.rendererInstances[mode] = renderer;
  131. return renderer;
  132. }
  133. }