Skip to content

Commit 61ff68b

Browse files
feat(classroom): 課題詳細の参加コードを1枚のカードに集約し配信ボタンを明確化
課題詳細に「課題を配信(GC)」と「この課題を共有(みんなの課題)」が併存し、 さらに参加コードが場所を取って全画面ボタンも別にあり、それぞれ何をするのか 分かりにくかった。参加コード周りを1枚のカードに整理: - 参加コードカード: 「参加コード:xxxxxx」+ アクション行 (全画面表示 / 招待リンクをコピー / Google Classroom に参加コードを共有) - 課題名の横にあった「課題を配信」ボタンを廃止し、カード内の 「Google Classroom に参加コードを共有」へ移動・改称(何をするか一目でわかる。 配信済みなら「Google Classroom で開く」)。GC 未連携なら非表示 - 招待リンクのコピーを詳細にも追加(従来は全画面表示の中だけ) ja.js / ja-Hira.js に joinCode.shareToGc / openInGc を対で追加。 みんなの課題の「この課題を共有」ボタンは (2) で一覧へ移すため今回は現状維持。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 69fed50 commit 61ff68b

4 files changed

Lines changed: 164 additions & 89 deletions

File tree

packages/scratch-gui/src/components/classroom-modal/classroom-modal.css

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,60 @@
278278
margin: 0.3rem 0;
279279
}
280280

281+
/* 参加コードカード (redesign): コードを一行にまとめ、その下に
282+
全画面 / 招待リンク / Google Classroom 共有 のアクションを並べる。 */
283+
.join-code-card {
284+
background-color: #f2f2f2;
285+
border: 2px dashed #d9d9d9;
286+
border-radius: 8px;
287+
padding: 0.5rem 0.6rem;
288+
margin: 0.3rem 0;
289+
}
290+
291+
.join-code-row {
292+
text-align: center;
293+
margin-bottom: 0.4rem;
294+
}
295+
296+
.join-code-actions {
297+
display: flex;
298+
flex-wrap: wrap;
299+
justify-content: center;
300+
gap: 0.4rem;
301+
}
302+
303+
.join-code-action {
304+
display: inline-flex;
305+
align-items: center;
306+
gap: 0.25rem;
307+
padding: 0.3rem 0.7rem;
308+
border: 1px solid #c8cdd8;
309+
border-radius: 6px;
310+
background-color: #fff;
311+
color: #575e75;
312+
font-size: 0.85rem;
313+
line-height: 1.2;
314+
cursor: pointer;
315+
text-decoration: none;
316+
white-space: nowrap;
317+
}
318+
319+
.join-code-action:hover {
320+
background-color: #f6f7fa;
321+
}
322+
323+
/* Google Classroom への共有は主要導線として強調 */
324+
.join-code-action-gc {
325+
border-color: #4c97ff;
326+
background-color: #e5f0ff;
327+
color: #3373cc;
328+
font-weight: bold;
329+
}
330+
331+
.join-code-action-gc:hover {
332+
background-color: #d6e7ff;
333+
}
334+
281335
.join-code-value {
282336
font-size: 1.5rem;
283337
font-weight: bold;

packages/scratch-gui/src/components/classroom-modal/teacher-class-detail.jsx

Lines changed: 106 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import classNames from 'classnames';
2-
import { FormattedMessage, useIntl } from 'react-intl';
2+
import { FormattedMessage } from 'react-intl';
33
import PropTypes from 'prop-types';
44
import React, { useCallback, useEffect, useRef, useState } from 'react';
55

@@ -49,7 +49,6 @@ const TeacherClassDetail = ({
4949
group,
5050
shared,
5151
}) => {
52-
const intl = useIntl();
5352
// Destructured with handle-prefixed names for the embedded editor
5453
// (react/jsx-handler-names requires handler props to look like handlers).
5554
const descEditor = assignmentEditor || {};
@@ -156,6 +155,13 @@ const TeacherClassDetail = ({
156155
onShowCodeDisplay(selectedClassroom.classroomId);
157156
}, [onShowCodeDisplay, selectedClassroom]);
158157

158+
const [inviteCopied, setInviteCopied] = useState(false);
159+
const handleCopyInvite = useCallback(() => {
160+
onCopyInviteLink(selectedClassroom);
161+
setInviteCopied(true);
162+
setTimeout(() => setInviteCopied(false), 2000);
163+
}, [onCopyInviteLink, selectedClassroom]);
164+
159165
const handleCloseCode = useCallback(() => {
160166
setShowCodeDisplay(false);
161167
onCloseCodeDisplay();
@@ -241,97 +247,108 @@ const TeacherClassDetail = ({
241247
onBlur={handleAssignmentNameBlur}
242248
onChange={handleAssignmentNameChange}
243249
/>
244-
{/* Google Classroom linkage now lives on the class
245-
(group), so an assignment posts to the group's
246-
course even when it has no courseId of its own.
247-
The posted/unposted branch below still keys off
248-
the assignment's own alternateLink. */}
249-
{(selectedClassroom.googleClassroomCourseId ||
250-
(group && group.googleClassroomCourseId)) &&
251-
(selectedClassroom.googleClassroomAlternateLink ? (
252-
<a
253-
className={
254-
styles.secondaryButton
255-
}
256-
data-testid="classroom-view-assignment"
257-
href={
258-
selectedClassroom.googleClassroomAlternateLink
259-
}
260-
rel="noopener noreferrer"
261-
target="_blank"
262-
>
263-
<img
264-
alt=""
265-
className={
266-
styles.gcImportIcon
267-
}
268-
src={
269-
googleClassroomIcon
270-
}
271-
/>
250+
</div>
251+
252+
253+
{/* 参加コードカード: コード + 全画面 / 招待リンク /
254+
Google Classroom に参加コードを共有 をまとめる。
255+
「配信」の何をするか(=参加コードを GC で生徒に
256+
配る)が一目でわかるよう文言・配置を整理した。 */}
257+
<div className={styles.joinCodeCard}>
258+
<div className={styles.joinCodeRow}>
259+
<span className={styles.joinCodeLabel}>
260+
<FormattedMessage
261+
defaultMessage="Join Code"
262+
description="Join code label"
263+
id="gui.classroom.joinCode.label"
264+
/>
265+
{': '}
266+
</span>
267+
<span
268+
className={styles.joinCodeValue}
269+
data-testid="classroom-detail-join-code"
270+
>
271+
{selectedClassroom.joinCode.toLowerCase()}
272+
</span>
273+
</div>
274+
<div className={styles.joinCodeActions}>
275+
<button
276+
className={styles.joinCodeAction}
277+
data-testid="classroom-detail-expand-code"
278+
type="button"
279+
onClick={handleShowCode}
280+
>
281+
{'⛶ '}
282+
<FormattedMessage
283+
defaultMessage="Show fullscreen"
284+
description="Fullscreen the join code"
285+
id="gui.classroom.joinCode.fullscreen"
286+
/>
287+
</button>
288+
<button
289+
className={styles.joinCodeAction}
290+
data-testid="classroom-detail-copy-link"
291+
type="button"
292+
onClick={handleCopyInvite}
293+
>
294+
{inviteCopied ? (
272295
<FormattedMessage
273-
defaultMessage="View Assignment"
274-
description="View posted assignment on Google Classroom"
275-
id="gui.classroom.postAssignment.viewAssignment"
276-
/>
277-
</a>
278-
) : (
279-
<button
280-
className={
281-
styles.secondaryButton
282-
}
283-
data-testid="classroom-post-assignment"
284-
onClick={
285-
onShowPostAssignment
286-
}
287-
>
288-
<img
289-
alt=""
290-
className={
291-
styles.gcImportIcon
292-
}
293-
src={
294-
googleClassroomIcon
295-
}
296+
defaultMessage="Copied"
297+
description="Confirmation after copying invite link"
298+
id="gui.classroom.codeDisplay.copied"
296299
/>
300+
) : (
297301
<FormattedMessage
298-
defaultMessage="Post Assignment"
299-
description="Post assignment to Google Classroom"
300-
id="gui.classroom.postAssignment.title"
302+
defaultMessage="Copy invite link"
303+
description="Button to copy classroom invite link"
304+
id="gui.classroom.codeDisplay.copyLink"
301305
/>
302-
</button>
303-
))}
304-
</div>
305-
306-
307-
{/* Join code with expand button */}
308-
<div className={styles.joinCodeDisplay}>
309-
<span className={styles.joinCodeLabel}>
310-
<FormattedMessage
311-
defaultMessage="Join Code"
312-
description="Join code label"
313-
id="gui.classroom.joinCode.label"
314-
/>
315-
{': '}
316-
</span>
317-
<span
318-
className={styles.joinCodeValue}
319-
data-testid="classroom-detail-join-code"
320-
>
321-
{selectedClassroom.joinCode.toLowerCase()}
322-
</span>
323-
<button
324-
className={styles.expandIconButton}
325-
data-testid="classroom-detail-expand-code"
326-
onClick={handleShowCode}
327-
title={intl.formatMessage({
328-
defaultMessage: 'Show fullscreen',
329-
description: 'Tooltip for join code fullscreen button',
330-
id: 'gui.classroom.joinCode.fullscreen',
331-
})}
332-
>
333-
{'⛶'}
334-
</button>
306+
)}
307+
</button>
308+
{/* Google Classroom linkage lives on the class
309+
(group), so an assignment posts to the group's
310+
course even without its own courseId. */}
311+
{(selectedClassroom.googleClassroomCourseId ||
312+
(group && group.googleClassroomCourseId)) &&
313+
(selectedClassroom.googleClassroomAlternateLink ? (
314+
<a
315+
className={classNames(styles.joinCodeAction, styles.joinCodeActionGc)}
316+
data-testid="classroom-view-assignment"
317+
href={selectedClassroom.googleClassroomAlternateLink}
318+
rel="noopener noreferrer"
319+
target="_blank"
320+
>
321+
<img
322+
alt=""
323+
className={styles.gcImportIcon}
324+
src={googleClassroomIcon}
325+
/>
326+
<FormattedMessage
327+
defaultMessage="Open in Google Classroom"
328+
description="Open the posted assignment on Google Classroom"
329+
id="gui.classroom.joinCode.openInGc"
330+
/>
331+
</a>
332+
) : (
333+
<button
334+
className={classNames(styles.joinCodeAction, styles.joinCodeActionGc)}
335+
data-testid="classroom-post-assignment"
336+
type="button"
337+
onClick={onShowPostAssignment}
338+
>
339+
<img
340+
alt=""
341+
className={styles.gcImportIcon}
342+
src={googleClassroomIcon}
343+
/>
344+
<FormattedMessage
345+
defaultMessage="Share join code to Google Classroom"
346+
description="Post the join code to Google Classroom for students"
347+
id="gui.classroom.joinCode.shareToGc"
348+
/>
349+
</button>
350+
))}
351+
</div>
335352
</div>
336353
{selectedClassroom.expiresAt && (
337354
<div className={styles.expiresAtText}>

packages/scratch-gui/src/locales/ja-Hira.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,8 @@ export default {
421421
'gui.classroom.codeDisplay.copied': 'コピーしました',
422422
'gui.classroom.teacherDetail.selectMember': 'しゅっせきばんごうをクリックしてせいとのしょうさいをみる',
423423
'gui.classroom.joinCode.fullscreen': 'ぜんがめんひょうじ',
424+
'gui.classroom.joinCode.shareToGc': 'Google Classroom に さんかコードを きょうゆう',
425+
'gui.classroom.joinCode.openInGc': 'Google Classroom で ひらく',
424426
'gui.classroom.teacherDetail.selectClassroom': 'サイドバーからクラスをせんたくしてください',
425427
'gui.classroom.management.loginPrompt': 'ログインしてクラスをかんり',
426428
'gui.classroom.management.loginDescription':

packages/scratch-gui/src/locales/ja.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ export default {
412412
'gui.classroom.codeDisplay.copied': 'コピーしました',
413413
'gui.classroom.teacherDetail.selectMember': '出席番号をクリックして生徒の詳細を見る',
414414
'gui.classroom.joinCode.fullscreen': '全画面表示',
415+
'gui.classroom.joinCode.shareToGc': 'Google Classroom に参加コードを共有',
416+
'gui.classroom.joinCode.openInGc': 'Google Classroom で開く',
415417
'gui.classroom.teacherDetail.selectClassroom': 'サイドバーからクラスを選択してください',
416418
'gui.classroom.management.loginPrompt': 'ログインしてクラスを管理',
417419
'gui.classroom.management.loginDescription': '学校のアカウントでログインして、クラスを作成・管理します。',

0 commit comments

Comments
 (0)