Просмотр исходного кода

Merge branch 'feat/notification' into imprv/jump-to-page-when-notification-clicked

# Conflicts:
#	packages/app/src/components/InAppNotification/InAppNotificationDropdown.tsx
kaori 4 лет назад
Родитель
Сommit
f687f0fffb

+ 26 - 1
CHANGELOG.md

@@ -1,9 +1,34 @@
 # Changelog
 
-## [Unreleased](https://github.com/weseek/growi/compare/v4.4.9...HEAD)
+## [Unreleased](https://github.com/weseek/growi/compare/v4.4.10...HEAD)
 
 *Please do not manually update this file. We've automated the process.*
 
+## [v4.4.10](https://github.com/weseek/growi/compare/v4.4.9...v4.4.10) - 2021-11-08
+
+### 🚀 Improvement
+
+- imprv: Sidebar content header style (#4526) @yuki-takei
+
+### 🐛 Bug Fixes
+
+- fix: /pages/info API is broken (#4602) @yuki-takei
+- fix: blackboard theme location in theme list (#4506) @ayaka0417
+
+### 🧰 Maintenance
+
+- support: Use SWR (#4487) @yuki-takei
+- support: Replaced PageList with SWR (#4498) @takayuki-t
+- support: Improve devcontainer (#4510) @yuki-takei
+- support: Update passport-ldpauth from ^2.0.0 to ^3.0.1 (#4578) @LuqmanHakim-Grune
+- ci(deps): bump validator from 13.6.0 to 13.7.0 (#4588) @dependabot
+- ci(deps-dev): bump stylelint from 13.2.0 to 14.0.1 (#4583) @dependabot
+- Bump browserslist from 4.0.1 to 4.16.6 (#3776) @dependabot
+- ci(deps-dev): bump colors from 1.2.5 to 1.4.0 (#4365) @dependabot
+- ci(deps-dev): bump on-headers from 1.0.1 to 1.0.2 (#4366) @dependabot
+- ci(deps-dev): bump jquery-ui from 1.12.1 to 1.13.0 (#4549) @dependabot
+- docs(page): Add docs to /page/info api (#4531) @Mxchaeltrxn
+
 ## [v4.4.9](https://github.com/weseek/growi/compare/v4.4.8...v4.4.9) - 2021-10-18
 
 ### 💎 Features

+ 1 - 1
lerna.json

@@ -1,7 +1,7 @@
 {
   "npmClient": "yarn",
   "useWorkspaces": true,
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "packages": [
     "packages/*"
   ]

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",

+ 2 - 2
packages/app/docker/README.md

@@ -10,8 +10,8 @@ GROWI Official docker image
 Supported tags and respective Dockerfile links
 ------------------------------------------------
 
-* [`4.4.9`, `4.4`, `4`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.9/docker/Dockerfile)
-* [`4.4.9-nocdn`, `4.4-nocdn`, `4-nocdn`, `latest-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.9/docker/Dockerfile)
+* [`4.4.10`, `4.4`, `4`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.10/docker/Dockerfile)
+* [`4.4.10-nocdn`, `4.4-nocdn`, `4-nocdn`, `latest-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.10/docker/Dockerfile)
 * [`4.3.3`, `4.3` (Dockerfile)](https://github.com/weseek/growi/blob/v4.3.3/docker/Dockerfile)
 * [`4.3.3-nocdn`, `4.3-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.3.3/docker/Dockerfile)
 

+ 11 - 11
packages/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/app",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "license": "MIT",
   "scripts": {
     "//// for production": "",
@@ -33,7 +33,7 @@
     "predev:ci": "run-p resources:*",
     "lint:typecheck": "npx tsc",
     "lint:eslint": "eslint --quiet \"**/*.{js,jsx,ts,tsx}\"",
-    "lint:styles": "stylelint src/**/*.scss",
+    "lint:styles": "stylelint src/**/*.scss --custom-syntax postcss-scss",
     "lint:swagger2openapi": "node node_modules/.bin/oas-validate tmp/swagger.json",
     "lint": "run-p lint:*",
     "test": "cross-env NODE_ENV=test jest --passWithNoTests -- ",
@@ -57,11 +57,11 @@
     "@browser-bunyan/console-formatted-stream": "^1.6.2",
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
-    "@growi/codemirror-textlint": "^4.4.10-RC.0",
-    "@growi/plugin-attachment-refs": "^4.4.10-RC.0",
-    "@growi/plugin-pukiwiki-like-linker": "^4.4.10-RC.0",
-    "@growi/plugin-lsx": "^4.4.10-RC.0",
-    "@growi/slack": "^4.4.10-RC.0",
+    "@growi/codemirror-textlint": "^4.4.11-RC.0",
+    "@growi/plugin-attachment-refs": "^4.4.11-RC.0",
+    "@growi/plugin-lsx": "^4.4.11-RC.0",
+    "@growi/plugin-pukiwiki-like-linker": "^4.4.11-RC.0",
+    "@growi/slack": "^4.4.11-RC.0",
     "@promster/express": "^5.1.0",
     "@promster/server": "^6.0.3",
     "@slack/events-api": "^3.0.0",
@@ -72,7 +72,7 @@
     "array.prototype.flatmap": "^1.2.2",
     "async-canvas-to-blob": "^1.0.3",
     "aws-sdk": "^2.88.0",
-    "axios": "^0.21.1",
+    "axios": "^0.24.0",
     "body-parser": "^1.18.2",
     "browser-bunyan": "^1.6.3",
     "bunyan": "^1.8.15",
@@ -121,7 +121,7 @@
     "nodemailer": "^6.6.2",
     "nodemailer-ses-transport": "~1.5.0",
     "openid-client": "=2.5.0",
-    "passport": "^0.4.0",
+    "passport": "^0.5.0",
     "passport-github": "^1.1.0",
     "passport-google-oauth20": "^2.0.0",
     "passport-http": "^0.3.0",
@@ -157,7 +157,7 @@
     "@alienfast/i18next-loader": "^1.0.16",
     "@atlaskit/drawer": "^5.3.7",
     "@atlaskit/navigation-next": "^8.0.5",
-    "@growi/ui": "^4.4.10-RC.0",
+    "@growi/ui": "^4.4.11-RC.0",
     "@handsontable/react": "=2.1.0",
     "@types/compression": "^1.7.0",
     "@types/express": "^4.17.11",
@@ -230,7 +230,7 @@
     "sticky-events": "^3.1.3",
     "style-loader": "^1.0.0",
     "styled-components": "^5.0.1",
-    "stylelint": "^13.2.0",
+    "stylelint": "^14.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "swagger2openapi": "^5.3.1",
     "swr": "^1.0.1",

+ 11 - 0
packages/app/resource/locales/en_US/translation.json

@@ -256,6 +256,17 @@
       "This tree": "Only children of this tree"
     }
   },
+  "in_app_notification": {
+    "notification_list": "In-App Notification List",
+    "see_all": "See All"
+  },
+  "in_app_notification_settings": {
+    "in_app_notification_settings": "In-App Notification Settings",
+    "subscribe_settings": "Settings to automatically subscribe (Receive notifications) to pages",
+    "default_subscribe_rules": {
+      "page_create": "Subscribe to the page when you create it."
+    }
+  },
   "editor_settings": {
     "editor_settings": "Editor Settings",
     "common_settings": {

+ 11 - 0
packages/app/resource/locales/ja_JP/translation.json

@@ -258,6 +258,17 @@
       "This tree": "この階層下の子ページのみ"
     }
   },
+  "in_app_notification": {
+    "notification_list": "アプリ内通知一覧",
+    "see_all": "通知一覧を見る"
+  },
+  "in_app_notification_settings": {
+    "in_app_notification_settings": "アプリ内通知設定",
+    "subscribe_settings": "自動でページをサブスクライブする(通知を受け取る)設定",
+    "default_subscribe_rules": {
+      "page_create": "ページを作成した時にそのページをサブスクライブします。"
+    }
+  },
   "editor_settings": {
     "editor_settings": "エディター設定",
     "common_settings": {

+ 11 - 0
packages/app/resource/locales/zh_CN/translation.json

@@ -237,6 +237,17 @@
 			"This tree": "当前分支以下内容"
 		}
   },
+  "in_app_notification": {
+    "notification_list": "应用内通知列表",
+    "see_all": "查看通知列表"
+  },
+  "in_app_notification_settings": {
+    "in_app_notification_settings": "在应用程序通知设置",
+    "subscribe_settings": "自动订阅(接收通知)页面的设置",
+    "default_subscribe_rules": {
+      "page_create": "创建页面时订阅页面。"
+    }
+  },
   "editor_settings": {
     "editor_settings": "编辑器设置",
     "common_settings": {

+ 4 - 1
packages/app/src/components/InAppNotification/InAppNotificationDropdown.tsx

@@ -2,8 +2,10 @@ import React, { useState, useEffect, FC } from 'react';
 import {
   Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
 } from 'reactstrap';
+import { useTranslation } from 'react-i18next';
 import loggerFactory from '~/utils/logger';
 
+
 import AppContainer from '../../client/services/AppContainer';
 import { withUnstatedContainers } from '../UnstatedUtils';
 import InAppNotificationList from './InAppNotificationList';
@@ -18,6 +20,7 @@ type Props = {
 };
 
 const InAppNotificationDropdown: FC<Props> = (props: Props) => {
+  const { t } = useTranslation();
   const { appContainer } = props;
 
   const [count, setCount] = useState(0);
@@ -80,7 +83,7 @@ const InAppNotificationDropdown: FC<Props> = (props: Props) => {
       <DropdownMenu className="px-2" right>
         <InAppNotificationList inAppNotificationData={inAppNotificationData} />
         <DropdownItem divider />
-        <a className="dropdown-item d-flex justify-content-center" href="/me/all-in-app-notifications">See All</a>
+        <a className="dropdown-item d-flex justify-content-center" href="/me/all-in-app-notifications">{ t('in_app_notification.see_all') }</a>
       </DropdownMenu>
     </Dropdown>
   );

+ 111 - 0
packages/app/src/components/Me/InAppNotificationSettings.tsx

@@ -0,0 +1,111 @@
+import React, {
+  FC, useState, useEffect, useCallback,
+} from 'react';
+
+import { useTranslation } from 'react-i18next';
+import { pullAllBy } from 'lodash';
+import { apiv3Get, apiv3Put } from '../../client/util/apiv3-client';
+import { toastSuccess, toastError } from '../../client/util/apiNotification';
+import { subscribeRuleNames, SubscribeRuleDescriptions } from '../../interfaces/in-app-notification-settings';
+
+type SubscribeRule = {
+  name: string,
+  isEnabled: boolean,
+}
+
+const subscribeRulesMenuItems = [
+  {
+    name: subscribeRuleNames.PAGE_CREATE,
+    description: SubscribeRuleDescriptions.PAGE_CREATE,
+  },
+];
+
+const isCheckedRule = (ruleName: string, subscribeRules: SubscribeRule[]) => (
+  subscribeRules.find(stateRule => (
+    stateRule.name === ruleName
+  ))?.isEnabled || false
+);
+
+const updateIsEnabled = (subscribeRules: SubscribeRule[], ruleName: string, isChecked: boolean) => {
+  const target = [{ name: ruleName, isEnabled: isChecked }];
+  return pullAllBy(subscribeRules, target, 'name').concat(target);
+};
+
+
+const InAppNotificationSettings: FC = () => {
+  const { t } = useTranslation();
+  const [subscribeRules, setSubscribeRules] = useState<SubscribeRule[]>([]);
+
+  const initializeInAppNotificationSettings = useCallback(async() => {
+    const { data } = await apiv3Get('/personal-setting/in-app-notification-settings');
+    const retrievedRules: SubscribeRule[] | null = data?.subscribeRules;
+
+    if (retrievedRules != null && retrievedRules.length > 0) {
+      setSubscribeRules(retrievedRules);
+    }
+  }, []);
+
+  const ruleCheckboxHandler = useCallback((ruleName: string, isChecked: boolean) => {
+    setSubscribeRules(prevState => updateIsEnabled(prevState, ruleName, isChecked));
+  }, []);
+
+  const updateSettingsHandler = useCallback(async() => {
+    try {
+      const { data } = await apiv3Put('/personal-setting/in-app-notification-settings', { subscribeRules });
+      setSubscribeRules(data.subscribeRules);
+      toastSuccess(t('toaster.update_successed', { target: 'InAppNotification Settings' }));
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [subscribeRules, setSubscribeRules, t]);
+
+  useEffect(() => {
+    initializeInAppNotificationSettings();
+  }, [initializeInAppNotificationSettings]);
+
+  return (
+    <>
+      <h2 className="border-bottom my-4">{t('in_app_notification_settings.subscribe_settings')}</h2>
+
+      <div className="form-group row">
+        <div className="offset-md-3 col-md-6 text-left">
+          {subscribeRulesMenuItems.map(rule => (
+            <div
+              key={rule.name}
+              className="custom-control custom-switch custom-checkbox-success"
+            >
+              <input
+                type="checkbox"
+                className="custom-control-input"
+                id={rule.name}
+                checked={isCheckedRule(rule.name, subscribeRules)}
+                onChange={e => ruleCheckboxHandler(rule.name, e.target.checked)}
+              />
+              <label className="custom-control-label" htmlFor={rule.name}>
+                <strong>{rule.name}</strong>
+              </label>
+              <p className="form-text text-muted small">
+                {t(rule.description)}
+              </p>
+            </div>
+          ))}
+        </div>
+      </div>
+
+      <div className="row my-3">
+        <div className="offset-4 col-5">
+          <button
+            type="button"
+            className="btn btn-primary"
+            onClick={updateSettingsHandler}
+          >
+            {t('Update')}
+          </button>
+        </div>
+      </div>
+    </>
+  );
+};
+
+export default InAppNotificationSettings;

+ 7 - 0
packages/app/src/components/Me/PersonalSettings.jsx

@@ -9,6 +9,7 @@ import PasswordSettings from './PasswordSettings';
 import ExternalAccountLinkedMe from './ExternalAccountLinkedMe';
 import ApiSettings from './ApiSettings';
 import { EditorSettings } from './EditorSettings';
+import InAppNotificationSettings from './InAppNotificationSettings';
 
 const PersonalSettings = (props) => {
 
@@ -46,6 +47,12 @@ const PersonalSettings = (props) => {
         i18n: t('editor_settings.editor_settings'),
         index: 4,
       },
+      in_app_notification_settings: {
+        Icon: () => <i className="icon-fw icon-bell"></i>,
+        Content: InAppNotificationSettings,
+        i18n: t('in_app_notification_settings.in_app_notification_settings'),
+        index: 5,
+      },
     };
   }, [t]);
 

+ 8 - 4
packages/app/src/interfaces/in-app-notification-settings.ts

@@ -1,13 +1,17 @@
 import { Schema } from 'mongoose';
 
-export enum subscribeRules {
+export enum subscribeRuleNames {
   PAGE_CREATE = 'PAGE_CREATE'
 }
-export interface IDefaultSubscribeRule {
-  name: subscribeRules;
+
+export enum SubscribeRuleDescriptions {
+  PAGE_CREATE = 'in_app_notification_settings.default_subscribe_rules.page_create',
+}
+export interface ISubscribeRule {
+  name: subscribeRuleNames;
   isEnabled: boolean;
 }
 export interface IInAppNotificationSettings {
   userId: Schema.Types.ObjectId;
-  defaultSubscribeRules: IDefaultSubscribeRule[];
+  subscribeRules: ISubscribeRule[];
 }

+ 3 - 3
packages/app/src/server/models/in-app-notification-settings.ts

@@ -1,16 +1,16 @@
 import { Schema, Model, Document } from 'mongoose';
 import { getOrCreateModel } from '@growi/core';
 
-import { IInAppNotificationSettings, subscribeRules } from '../../interfaces/in-app-notification-settings';
+import { IInAppNotificationSettings, subscribeRuleNames } from '../../interfaces/in-app-notification-settings';
 
 export interface InAppNotificationSettingsDocument extends IInAppNotificationSettings, Document {}
 export type InAppNotificationSettingsModel = Model<InAppNotificationSettingsDocument>
 
 const inAppNotificationSettingsSchema = new Schema<IInAppNotificationSettings>({
   userId: { type: String },
-  defaultSubscribeRules: [
+  subscribeRules: [
     {
-      name: { type: String, require: true, enum: subscribeRules },
+      name: { type: String, require: true, enum: subscribeRuleNames },
       isEnabled: { type: Boolean },
     },
   ],

+ 3 - 3
packages/app/src/server/routes/apiv3/personal-setting.js

@@ -577,15 +577,15 @@ module.exports = (crowi) => {
   // eslint-disable-next-line max-len
   router.put('/in-app-notification-settings', accessTokenParser, loginRequiredStrictly, csrf, validator.inAppNotificationSettings, apiV3FormValidator, async(req, res) => {
     const query = { userId: req.user.id };
-    const defaultSubscribeRules = req.body.defaultSubscribeRules;
+    const subscribeRules = req.body.subscribeRules;
 
-    if (defaultSubscribeRules == null) {
+    if (subscribeRules == null) {
       return res.apiv3Err('no-rules-found');
     }
 
     const options = { upsert: true, new: true, runValidators: true };
     try {
-      const response = await InAppNotificationSettings.findOneAndUpdate(query, { defaultSubscribeRules }, options);
+      const response = await InAppNotificationSettings.findOneAndUpdate(query, { subscribeRules }, options);
       return res.apiv3(response);
     }
     catch (err) {

+ 2 - 4
packages/app/src/server/views/me/all-in-app-notifications.html

@@ -1,15 +1,13 @@
 {% extends '../layout/layout.html' %}
 
-<!-- TODO: apply i18n by #80104 -->
-{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('All In-App Notifications')) }}{% endblock %}
+{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('in_app_notification.notification_list')) }}{% endblock %}
 
 {% block layout_main %}
 
 {% block content_header_wrapper %}
 <header class="py-3">
   <div class="container-fluid">
-    <!-- TODO: apply i18n by #80104 -->
-    <h1 class="title">All In-App Notifications</h1>
+    <h1 class="title">{{ t('in_app_notification.notification_list') }}</h1>
   </div>
 </header>
 <div id="grw-fav-sticky-trigger" class="sticky-top"></div>

+ 1 - 1
packages/codemirror-textlint/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/codemirror-textlint",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "license": "MIT",
   "main": "dist/index.js",
   "scripts": {

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/core",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI Core Libraries",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/plugin-attachment-refs/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/plugin-attachment-refs",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI Plugin to add ref/refimg/refs/refsimg tags",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/plugin-lsx/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/plugin-lsx",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI plugin to list pages",
   "license": "MIT",
   "keywords": [

+ 2 - 2
packages/plugin-pukiwiki-like-linker/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/plugin-pukiwiki-like-linker",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI plugin to add PukiwikiLikeLinker",
   "license": "MIT",
   "keywords": [
@@ -22,7 +22,7 @@
   },
   "devDependencies": {
     "browser-bunyan": "^1.6.3",
-    "stylelint": "^13.2.0",
+    "stylelint": "^14.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "tsc-alias": "^1.2.9"
   }

+ 2 - 2
packages/slack/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slack",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "license": "MIT",
   "main": "dist/index.js",
   "typings": "dist/index.d.ts",
@@ -14,7 +14,7 @@
   },
   "dependencies": {
     "@slack/oauth": "^2.0.1",
-    "axios": "^0.21.1",
+    "axios": "^0.24.0",
     "browser-bunyan": "^1.6.3",
     "bunyan": "^1.8.15",
     "extensible-custom-error": "^0.0.7",

+ 3 - 3
packages/slackbot-proxy/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slackbot-proxy",
-  "version": "4.4.10-slackbot-proxy.0",
+  "version": "4.4.11-slackbot-proxy.0",
   "license": "MIT",
   "scripts": {
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
@@ -25,7 +25,7 @@
   },
   "dependencies": {
     "@godaddy/terminus": "^4.9.0",
-    "@growi/slack": "^4.4.10-RC.0",
+    "@growi/slack": "^4.4.11-RC.0",
     "@slack/oauth": "^2.0.1",
     "@slack/web-api": "^6.2.4",
     "@tsed/common": "^6.43.0",
@@ -33,7 +33,7 @@
     "@tsed/platform-express": "^6.43.0",
     "@tsed/swagger": "^6.43.0",
     "@tsed/typeorm": "^6.43.0",
-    "axios": "^0.21.1",
+    "axios": "^0.24.0",
     "browser-bunyan": "^1.6.3",
     "bunyan": "^1.8.15",
     "compression": "^1.7.4",

+ 1 - 1
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/ui",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI UI Libraries",
   "license": "MIT",
   "keywords": [

Разница между файлами не показана из-за своего большого размера
+ 131 - 440
yarn.lock


Некоторые файлы не были показаны из-за большого количества измененных файлов