misskey icon indicating copy to clipboard operation
misskey copied to clipboard

feat: 新カスタム絵文字管理画面(β)の追加

Open samunohito opened this issue 1 year ago • 60 comments

What

カスタム絵文字の登録画面をリニューアルし、複数の絵文字に対して同時に登録・更新作業を行えるようにしました。

Why

resolve #10996

Additional info (optional)

既存のカスタム絵文字管理画面はそのままのこし、新画面はβ版の位置づけで追加しています(安定したら完全に置き換える考え)。

Checklist

  • [x] Read the contribution guide
  • [x] Test working in a local environment
  • [x] (If needed) Add story of storybook
  • [x] (If needed) Update CHANGELOG.md
  • [ ] (If possible) Add tests

samunohito avatar Feb 28 '24 23:02 samunohito

Codecov Report

Attention: Patch coverage is 4.61936% with 6277 lines in your changes missing coverage. Please review.

Project coverage is 40.46%. Comparing base (59e8360) to head (6baf88e). Report is 1 commits behind head on develop.

Files Patch % Lines
packages/frontend/src/components/grid/MkGrid.vue 0.00% 1340 Missing and 1 partial :warning:
...c/pages/admin/custom-emojis-manager.local.list.vue 0.00% 713 Missing and 1 partial :warning:
...ges/admin/custom-emojis-manager.local.register.vue 0.00% 465 Missing and 1 partial :warning:
...d/src/pages/admin/custom-emojis-manager.remote.vue 0.00% 394 Missing and 1 partial :warning:
...ckages/frontend/src/components/grid/MkDataCell.vue 0.00% 390 Missing and 1 partial :warning:
...rontend/src/components/grid/MkGrid.stories.impl.ts 0.00% 222 Missing and 1 partial :warning:
...ages/frontend/src/components/grid/MkHeaderCell.vue 0.00% 215 Missing and 1 partial :warning:
...ackages/frontend/src/components/grid/grid-utils.ts 0.00% 214 Missing and 1 partial :warning:
...ges/frontend/src/components/MkRoleSelectDialog.vue 0.00% 200 Missing and 1 partial :warning:
packages/backend/src/core/CustomEmojiService.ts 17.72% 181 Missing :warning:
... and 32 more
Additional details and impacted files
@@             Coverage Diff              @@
##           develop   #13473       +/-   ##
============================================
+ Coverage    20.14%   40.46%   +20.31%     
============================================
  Files          725     1582      +857     
  Lines       100521   203550   +103029     
  Branches      1051     3488     +2437     
============================================
+ Hits         20249    82364    +62115     
- Misses       79729   120593    +40864     
- Partials       543      593       +50     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov[bot] avatar Feb 28 '24 23:02 codecov[bot]

このPRによるapi.jsonの差分

差分はこちら
--- base
+++ head
@@ -6131,6 +6131,15 @@
                       }
                     }
                   },
+                  "UNSUPPORTED_FILE_TYPE": {
+                    "value": {
+                      "error": {
+                        "message": "Unsupported file type.",
+                        "code": "UNSUPPORTED_FILE_TYPE",
+                        "id": "f7599d96-8750-af68-1633-9575d625c1a7"
+                      }
+                    }
+                  },
                   "DUPLICATE_NAME": {
                     "value": {
                       "error": {
@@ -8160,6 +8169,295 @@
         }
       }
     },
+    "/v2/admin/emoji/list": {
+      "post": {
+        "operationId": "v2___admin___emoji___list",
+        "summary": "v2/admin/emoji/list",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *read:admin:emoji*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/v2/admin/emoji/list.ts"
+        },
+        "tags": [
+          "admin"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "requestBody": {
+          "required": true,
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "query": {
+                    "type": [
+                      "object",
+                      "null"
+                    ],
+                    "properties": {
+                      "updatedAtFrom": {
+                        "type": "string"
+                      },
+                      "updatedAtTo": {
+                        "type": "string"
+                      },
+                      "name": {
+                        "type": "string"
+                      },
+                      "host": {
+                        "type": "string"
+                      },
+                      "uri": {
+                        "type": "string"
+                      },
+                      "publicUrl": {
+                        "type": "string"
+                      },
+                      "originalUrl": {
+                        "type": "string"
+                      },
+                      "type": {
+                        "type": "string"
+                      },
+                      "aliases": {
+                        "type": "string"
+                      },
+                      "category": {
+                        "type": "string"
+                      },
+                      "license": {
+                        "type": "string"
+                      },
+                      "isSensitive": {
+                        "type": "boolean"
+                      },
+                      "localOnly": {
+                        "type": "boolean"
+                      },
+                      "hostType": {
+                        "type": "string",
+                        "enum": [
+                          "local",
+                          "remote",
+                          "all"
+                        ],
+                        "default": "all"
+                      },
+                      "roleIds": {
+                        "type": "array",
+                        "items": {
+                          "type": "string",
+                          "format": "misskey:id"
+                        }
+                      }
+                    }
+                  },
+                  "sinceId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  },
+                  "untilId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  },
+                  "limit": {
+                    "type": "integer",
+                    "minimum": 1,
+                    "maximum": 100,
+                    "default": 10
+                  },
+                  "page": {
+                    "type": "integer"
+                  },
+                  "sortKeys": {
+                    "type": "array",
+                    "default": [
+                      "-id"
+                    ],
+                    "items": {
+                      "type": "string",
+                      "enum": [
+                        "+id",
+                        "-id",
+                        "+updatedAt",
+                        "-updatedAt",
+                        "+name",
+                        "-name",
+                        "+host",
+                        "-host",
+                        "+uri",
+                        "-uri",
+                        "+publicUrl",
+                        "-publicUrl",
+                        "+type",
+                        "-type",
+                        "+aliases",
+                        "-aliases",
+                        "+category",
+                        "-category",
+                        "+license",
+                        "-license",
+                        "+isSensitive",
+                        "-isSensitive",
+                        "+localOnly",
+                        "-localOnly",
+                        "+roleIdsThatCanBeUsedThisEmojiAsReaction",
+                        "-roleIdsThatCanBeUsedThisEmojiAsReaction"
+                      ]
+                    }
+                  }
+                }
+              }
+            }
+          }
+        },
+        "responses": {
+          "200": {
+            "description": "OK (with results)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "object",
+                  "properties": {
+                    "emojis": {
+                      "type": "array",
+                      "items": {
+                        "type": "object",
+                        "$ref": "#/components/schemas/EmojiDetailedAdmin"
+                      }
+                    },
+                    "count": {
+                      "type": "integer"
+                    },
+                    "allCount": {
+                      "type": "integer"
+                    },
+                    "allPages": {
+                      "type": "integer"
+                    }
+                  },
+                  "required": [
+                    "emojis",
+                    "count",
+                    "allCount",
+                    "allPages"
+                  ]
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INVALID_PARAM": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid param.",
+                        "code": "INVALID_PARAM",
+                        "id": "3d81ceae-475f-4600-b2a8-2bc116157532"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Authentication error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "CREDENTIAL_REQUIRED": {
+                    "value": {
+                      "error": {
+                        "message": "Credential required.",
+                        "code": "CREDENTIAL_REQUIRED",
+                        "id": "1384574d-a912-4b81-8601-c7b1c4085df1"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Forbidden error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "AUTHENTICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Authentication failed. Please ensure your token is correct.",
+                        "code": "AUTHENTICATION_FAILED",
+                        "id": "b0a7f5f8-dc2f-4171-b91f-de88ad238e14"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "418": {
+            "description": "I'm Ai",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "I_AM_AI": {
+                    "value": {
+                      "error": {
+                        "message": "You sent a request to Ai-chan, Misskey's showgirl, instead of the server.",
+                        "code": "I_AM_AI",
+                        "id": "60c46cd1-f23a-46b1-bebe-5d2b73951a84"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "500": {
+            "description": "Internal server error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INTERNAL_ERROR": {
+                    "value": {
+                      "error": {
+                        "message": "Internal error occurred. Please contact us if the error persists.",
+                        "code": "INTERNAL_ERROR",
+                        "id": "5d37dbcb-891e-41ca-a3d6-e690c97775ac"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
     "/admin/federation/delete-all-files": {
       "post": {
         "operationId": "admin___federation___delete-all-files",
@@ -79924,6 +80222,110 @@
           "roleIdsThatCanBeUsedThisEmojiAsReaction"
         ]
       },
+      "EmojiDetailedAdmin": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string",
+            "format": "id"
+          },
+          "updatedAt": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "format": "date-time"
+          },
+          "name": {
+            "type": "string"
+          },
+          "host": {
+            "type": [
+              "string",
+              "null"
+            ],
+            "description": "The local host is represented with `null`."
+          },
+          "publicUrl": {
+            "type": "string"
+          },
+          "originalUrl": {
+            "type": "string"
+          },
+          "uri": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "type": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "aliases": {
+            "type": "array",
+            "items": {
+              "type": "string",
+              "format": "id"
+            }
+          },
+          "category": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "license": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
+          "localOnly": {
+            "type": "boolean"
+          },
+          "isSensitive": {
+            "type": "boolean"
+          },
+          "roleIdsThatCanBeUsedThisEmojiAsReaction": {
+            "type": "array",
+            "items": {
+              "type": "object",
+              "properties": {
+                "id": {
+                  "type": "string",
+                  "format": "misskey:id"
+                },
+                "name": {
+                  "type": "string"
+                }
+              },
+              "required": [
+                "id",
+                "name"
+              ]
+            }
+          }
+        },
+        "required": [
+          "id",
+          "updatedAt",
+          "name",
+          "host",
+          "publicUrl",
+          "originalUrl",
+          "uri",
+          "type",
+          "aliases",
+          "category",
+          "license",
+          "localOnly",
+          "isSensitive",
+          "roleIdsThatCanBeUsedThisEmojiAsReaction"
+        ]
+      },
       "Flash": {
         "type": "object",
         "properties": {

Get diff files from Workflow Page

github-actions[bot] avatar Feb 28 '24 23:02 github-actions[bot]

lintこけてんな…あとでなおします

samunohito avatar Feb 28 '24 23:02 samunohito

カテゴリ限定検索等が可能なUIがあるようなので、このPRで #12546 もClose出来そうです。

Sayamame-beans avatar Mar 05 '24 09:03 Sayamame-beans

/preview

syuilo avatar Mar 05 '24 09:03 syuilo

MkGrid.vueでtableタグ使っているのは何か理由あるかしら

syuilo avatar Mar 17 '24 08:03 syuilo

多機能なテーブル状のコンポーネントが元々の構想だったので、そのままtableタグを使いました

samunohito avatar Mar 17 '24 11:03 samunohito

ほむ tableでしか実現できない機能とかがあるわけではない?

syuilo avatar Mar 17 '24 11:03 syuilo

tableならではとなると… もしdivの集合体などにした場合、カラムの幅変更周りの挙動に影響が出るかもしれません(未検証)

samunohito avatar Mar 17 '24 12:03 samunohito

横のスクロールバーが下にあるからテーブルが長いと横スクロールするために一番下までスクロールしないといけないのが不便化も image

syuilo avatar Mar 18 '24 09:03 syuilo

スクロールバーはどうしようもないですね… Shift+マウスホイールで横にスクロールできるので、これで何とかなりませんか…?

samunohito avatar Mar 19 '24 23:03 samunohito

スクロールバー部分だけstickyにするとか

syuilo avatar Mar 20 '24 07:03 syuilo

CSS Modulesが使われてないとこが所々あるわべ

syuilo avatar Mar 28 '24 09:03 syuilo

StickyContainerが効いてないのが謎

syuilo avatar Mar 28 '24 09:03 syuilo

custom-emojis-manager.local.vue とかで overflow: scroll; してて縦に二重スクロールバー表示されるのはUXが悪そう

syuilo avatar Mar 28 '24 09:03 syuilo

custom-emojis-manager.local.vue とかで overflow: scroll; してて縦に二重スクロールバー表示されるのはUXが悪そう

二重になります? image こっちだとウィンドウサイズを変えたりしても↑の右端に見えてる奴だけなんですが

samunohito avatar Mar 28 '24 10:03 samunohito

image

syuilo avatar Mar 28 '24 11:03 syuilo

二重に出る

syuilo avatar Mar 28 '24 11:03 syuilo

ここでスクロールできるようにする必要はなさそう

syuilo avatar Mar 28 '24 11:03 syuilo

あれぇ…

縦スクロールを無効化して支障無さそうなら、無効化します

samunohito avatar Mar 28 '24 11:03 samunohito

ひとまず、 cf95082 にて

CSS Modulesが使われてないとこが所々あるわべ

を対処しました

samunohito avatar Mar 28 '24 12:03 samunohito

二重に出る

overflow-yをhiddenにしてみたけど直ったかしら…(こちらでは元々スクロールバーが出ないので確認できない)

0bc2401

samunohito avatar Mar 28 '24 23:03 samunohito

ひとまずMkStickyContainerは効くようになったけど、横にスクロールするとボタンなどの表示位置などが非常に微妙なことになるので、もうちょい色々試します image image

samunohito avatar Mar 29 '24 00:03 samunohito

grid component内部はスクロールできるようにすれば解決しそう

syuilo avatar Mar 29 '24 03:03 syuilo

↑試したけどtableタグは挙動が特殊っぽい

syuilo avatar Mar 29 '24 03:03 syuilo

gridArea に overflow: scroll 追加したらいい感じになった

syuilo avatar Mar 29 '24 03:03 syuilo

テーブルのheader部分やスクロールバー部分をstickyにしたいことなどを考えるとtableタグ使うことはできなそう

syuilo avatar Mar 29 '24 06:03 syuilo

引き継ぎます

syuilo avatar Mar 29 '24 06:03 syuilo

(後はしゅいろさんがイイカンジにしてくれるということかしら…)

samunohito avatar Mar 29 '24 10:03 samunohito

うーん難しいわね

syuilo avatar Mar 29 '24 10:03 syuilo