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

refs 112131: questionnaire interfaces

Futa Arai 3 лет назад
Родитель
Сommit
8d7e239a10

+ 4 - 4
.devcontainer/Dockerfile

@@ -3,7 +3,7 @@
 # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
 #-------------------------------------------------------------------------------------------------------------
 
-FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-16
+FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-16-bullseye
 
 # The node image includes a non-root user with sudo access. Use the
 # "remoteUser" property in devcontainer.json to use it. On Linux, update
@@ -33,13 +33,13 @@ RUN chown -R $USER_UID:$USER_GID /home/$USERNAME /workspace;
 ENV DEBIAN_FRONTEND=noninteractive
 
 # Prepare to install Chrome for VRT
-RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
-RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
+# RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
+# RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
 
 RUN apt-get update \
    && apt-get -y install --no-install-recommends git-lfs \
       # Chrome
-      google-chrome-stable \
+      # google-chrome-stable \
       # for Cypress
       libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb fonts-noto-cjk \
 

+ 2 - 0
packages/app/.env.development

@@ -18,6 +18,8 @@ HACKMD_URI="http://localhost:3010"
 HACKMD_URI_FOR_SERVER="http://hackmd:3000"
 OGP_URI="http://ogp:8088"
 GROWI_QUESTIONNAIRE_URI="http://host.docker.internal:3003"
+QUESTIONNAIRE_CRON_SCHEDULE="* * * * *"
+QUESTIONNAIRE_CRON_MAX_HOURS_UNTIL_REQUEST=1/60
 # DRAWIO_URI="http://localhost:8080/?offline=1&https=0"
 # S2SMSG_PUBSUB_SERVER_TYPE=nchan
 # PUBLISH_OPEN_API=true

+ 16 - 0
packages/app/src/interfaces/questionnaire/condition.ts

@@ -0,0 +1,16 @@
+import { GrowiServiceType } from './growi-info';
+import { UserType } from './user-info';
+
+interface UserCondition {
+  types: UserType[] // アンケート対象ユーザータイプ
+}
+
+interface GrowiCondition {
+  types: GrowiServiceType[] // アンケート対象 GROWI タイプ
+  versionRegExps: string[] // アンケート対象 GROWI バージョン正規表現
+}
+
+export interface ICondition {
+  user: UserCondition
+  growi: GrowiCondition
+}

+ 47 - 0
packages/app/src/interfaces/questionnaire/growi-info.ts

@@ -0,0 +1,47 @@
+import * as os from 'node:os';
+
+export const GrowiServiceType = {
+  cloud: 'cloud',
+  privateCloud: 'private-cloud',
+  onPremise: 'on-premise',
+  others: 'others',
+} as const;
+const GrowiWikiType = { open: 'open', closed: 'closed' } as const;
+const GrowiAttachmentType = {
+  aws: 'aws',
+  gcs: 'gcs',
+  gridfs: 'gridfs',
+  local: 'local',
+  none: 'none',
+} as const;
+const GrowiDeploymentType = {
+  officialHelmChart: 'official-helm-chart',
+  growiDockerCompose: 'growi-docker-compose',
+  node: 'node',
+  others: 'others',
+} as const;
+
+export type GrowiServiceType = typeof GrowiServiceType[keyof typeof GrowiServiceType]
+type GrowiWikiType = typeof GrowiWikiType[keyof typeof GrowiWikiType]
+type GrowiAttachmentType = typeof GrowiAttachmentType[keyof typeof GrowiAttachmentType]
+type GrowiDeploymentType = typeof GrowiDeploymentType[keyof typeof GrowiDeploymentType]
+
+interface IGrowiOSInfo {
+  type?: ReturnType<typeof os.type>
+  platform?: ReturnType<typeof os.platform>
+  arch?: ReturnType<typeof os.arch>
+  totalmem?: ReturnType<typeof os.totalmem>
+}
+
+export interface IGrowiInfo {
+  version: string
+  appSiteUrl: string // hash 化されている場合もある
+  type: GrowiServiceType
+  currentUsersCount: number
+  currentActiveUsersCount: number
+  wikiType: GrowiWikiType
+  attachmentType: GrowiAttachmentType
+  activeExternalAccountTypes?: string
+  osInfo?: IGrowiOSInfo
+  deploymentType?: GrowiDeploymentType
+}

+ 8 - 0
packages/app/src/interfaces/questionnaire/question.ts

@@ -0,0 +1,8 @@
+export const QuestionType = { points: 'points', text: 'text' } as const;
+
+type QuestionType = typeof QuestionType[keyof typeof QuestionType];
+
+export interface IQuestion {
+  type: QuestionType // アンケートの回答形式
+  text: string // アンケートの文章
+}

+ 9 - 0
packages/app/src/interfaces/questionnaire/questionnaire-order.ts

@@ -0,0 +1,9 @@
+import { ICondition } from './questionnaire/condition';
+import { IQuestion } from './question';
+
+export interface IQuestionnaireOrder {
+  showFrom: Date
+  showUntil: Date
+  questions: IQuestion[]
+  condition: ICondition
+}

+ 9 - 0
packages/app/src/interfaces/questionnaire/user-info.ts

@@ -0,0 +1,9 @@
+export const UserType = { admin: 'admin', general: 'general' } as const;
+
+export type UserType = typeof UserType[keyof typeof UserType];
+
+export interface IUserInfo {
+  userIdHash: string // 生のユーザー ID を appSiteUrl を hash 化したものを salt にして hash 化
+  type: UserType
+  userCreatedAt: Date // 回答ユーザーの作成日時(登録日時)
+}

+ 25 - 0
packages/app/src/server/models/questionnaire/questionnaire-order.ts

@@ -0,0 +1,25 @@
+import { Model, Schema, Document } from 'mongoose';
+
+import { IQuestionnaireOrder } from '~/interfaces/questionnaire/questionnaire-order';
+import { getOrCreateModel } from '~/server/util/mongoose-utils';
+
+import conditionSchema from './schema/condition';
+import questionSchema from './schema/question';
+
+export interface QuestionnaireOrderDocument extends IQuestionnaireOrder, Document {}
+
+export type QuestionnaireOrderModel = Model<QuestionnaireOrderDocument>
+
+function showDateValidator(value) {
+  // `this` is the mongoose document
+  return this.showFrom <= value;
+}
+
+const questionnaireOrderSchema = new Schema<IQuestionnaireOrder>({
+  showFrom: { type: Date, required: true },
+  showUntil: { type: Date, required: true, validate: [showDateValidator, 'showFrom must be before showUntil'] },
+  questions: [questionSchema],
+  condition: { type: conditionSchema, required: true },
+}, { timestamps: true });
+
+export default getOrCreateModel<QuestionnaireOrderDocument, QuestionnaireOrderModel>('QuestionnaireOrder', questionnaireOrderSchema);

+ 17 - 0
packages/app/src/server/models/questionnaire/schema/condition.ts

@@ -0,0 +1,17 @@
+import { Schema } from 'mongoose';
+
+import { ICondition } from '~/interfaces/questionnaire/condition';
+import { GrowiServiceType } from '~/interfaces/questionnaire/growi-info';
+import { UserType } from '~/interfaces/questionnaire/user-info';
+
+const conditionSchema = new Schema<ICondition>({
+  user: {
+    types: [{ type: String, enum: Object.values(UserType) }],
+  },
+  growi: {
+    types: [{ type: String, enum: Object.values(GrowiServiceType) }],
+    versionRegExps: [String],
+  },
+});
+
+export default conditionSchema;

+ 10 - 0
packages/app/src/server/models/questionnaire/schema/question.ts

@@ -0,0 +1,10 @@
+import { Schema } from 'mongoose';
+
+import { IQuestion, QuestionType } from '~/interfaces/questionnaire/question';
+
+const questionSchema = new Schema<IQuestion>({
+  type: { type: String, required: true, enum: Object.values(QuestionType) },
+  text: { type: String, required: true },
+}, { timestamps: true });
+
+export default questionSchema;

+ 3 - 0
packages/app/src/server/service/questionnaire-cron.ts

@@ -1,6 +1,7 @@
 import axios from '~/utils/axios';
 
 import Crowi from '../crowi';
+import { QuestionnaireOrderDocument } from '../models/questionnaire/questionnaire-order';
 
 const nodeCron = require('node-cron');
 
@@ -39,7 +40,9 @@ class QuestionnaireCronService {
 
       try {
         const response = await axios.get(`${this.growiQuestionnaireUri}/questionnaire-order/index`);
+        const questionnaireOrders: QuestionnaireOrderDocument[] = response.data.questionnaireOrders;
         console.log(response.data);
+        console.log(questionnaireOrders);
       }
       catch (e) {
         console.log(e);