AppContainer.js 4.4 KB

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