feat: 프런트엔드에서 합성 기관코드를 반영하고 policy 특례를 제거
기관 코드가 6자(008_02 등)로 늘어난 데 맞춰 OrgList의 코드 칸 폭을 넓히고, OrgOverview의 Mattermost 채널 링크 생성에 남아 있던 치안정책연구소 -policy- 특례를 제거했다(연번 자체가 하위기관까지 구분하므로 더 이상 필요 없음).
@5c7c71b0b916bfe1ba084257ba28f9102df14de2
--- frontend/src/components/OrgList.test.tsx
+++ frontend/src/components/OrgList.test.tsx
... | ... | @@ -5,12 +5,12 @@ |
| 5 | 5 |
|
| 6 | 6 |
const orgs: Org[] = [ |
| 7 | 7 |
{
|
| 8 |
- id: 1, orgNo: '001', orgName: '국제방송교류재단', status: 'ACTIVE', |
|
| 8 |
+ id: 1, orgNo: '001_00', orgName: '국제방송교류재단', status: 'ACTIVE', |
|
| 9 | 9 |
applicant: null, mj: null, lawyer: null, lawyerAssignedDate: null, |
| 10 | 10 |
channelIdMj: 'a', channelIdLaw: 'b', |
| 11 | 11 |
}, |
| 12 | 12 |
{
|
| 13 |
- id: 2, orgNo: '008', orgName: '경찰청_치안정책연구소', status: 'INFO_PENDING', |
|
| 13 |
+ id: 2, orgNo: '008_01', orgName: '경찰청_치안정책연구소', status: 'INFO_PENDING', |
|
| 14 | 14 |
applicant: null, mj: null, lawyer: null, lawyerAssignedDate: null, |
| 15 | 15 |
channelIdMj: null, channelIdLaw: null, |
| 16 | 16 |
}, |
... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 |
it('연번과 기관명을 보여준다', () => {
|
| 21 | 21 |
render(<OrgList orgs={orgs} selectedId={null} onSelect={() => {}} />)
|
| 22 | 22 |
|
| 23 |
- expect(screen.getByText('001')).toBeTruthy()
|
|
| 23 |
+ expect(screen.getByText('001_00')).toBeTruthy()
|
|
| 24 | 24 |
expect(screen.getByText('국제방송교류재단')).toBeTruthy()
|
| 25 | 25 |
expect(screen.getByText('경찰청_치안정책연구소')).toBeTruthy()
|
| 26 | 26 |
}) |
... | ... | @@ -50,19 +50,19 @@ |
| 50 | 50 |
<OrgList orgs={orgs} selectedId={null} onSelect={() => {}} collapsed onToggle={() => {}} />,
|
| 51 | 51 |
) |
| 52 | 52 |
|
| 53 |
- expect(screen.getByText('001')).toBeTruthy()
|
|
| 53 |
+ expect(screen.getByText('001_00')).toBeTruthy()
|
|
| 54 | 54 |
expect(screen.queryByText('국제방송교류재단')).toBeNull()
|
| 55 | 55 |
expect(screen.queryByPlaceholderText('기관명 검색')).toBeNull()
|
| 56 | 56 |
|
| 57 |
- const item = screen.getByRole('button', { name: '001 국제방송교류재단' })
|
|
| 58 |
- expect(item).toHaveAttribute('title', '001 국제방송교류재단 (운영 중)')
|
|
| 57 |
+ const item = screen.getByRole('button', { name: '001_00 국제방송교류재단' })
|
|
| 58 |
+ expect(item).toHaveAttribute('title', '001_00 국제방송교류재단 (운영 중)')
|
|
| 59 | 59 |
}) |
| 60 | 60 |
|
| 61 | 61 |
it('접힌 상태에서도 기관을 선택할 수 있다', () => {
|
| 62 | 62 |
const onSelect = vi.fn() |
| 63 | 63 |
render(<OrgList orgs={orgs} selectedId={null} onSelect={onSelect} collapsed />)
|
| 64 | 64 |
|
| 65 |
- fireEvent.click(screen.getByRole('button', { name: '001 국제방송교류재단' }))
|
|
| 65 |
+ fireEvent.click(screen.getByRole('button', { name: '001_00 국제방송교류재단' }))
|
|
| 66 | 66 |
|
| 67 | 67 |
expect(onSelect).toHaveBeenCalledWith(1) |
| 68 | 68 |
}) |
--- frontend/src/components/OrgList.tsx
+++ frontend/src/components/OrgList.tsx
... | ... | @@ -59,7 +59,9 @@ |
| 59 | 59 |
selectedId === org.id ? 'bg-blue-50' : '' |
| 60 | 60 |
}`} |
| 61 | 61 |
> |
| 62 |
- <span className="text-[11px] font-medium text-gray-600">{org.orgNo}</span>
|
|
| 62 |
+ <span className="w-14 text-center text-[11px] font-medium text-gray-600"> |
|
| 63 |
+ {org.orgNo}
|
|
| 64 |
+ </span> |
|
| 63 | 65 |
<span className={`h-1.5 w-1.5 rounded-full ${STATUS_DOT[org.status]}`} />
|
| 64 | 66 |
</button> |
| 65 | 67 |
</li> |
... | ... | @@ -102,7 +104,7 @@ |
| 102 | 104 |
selectedId === org.id ? 'bg-blue-50' : '' |
| 103 | 105 |
}`} |
| 104 | 106 |
> |
| 105 |
- <span className="w-9 shrink-0 text-xs text-gray-500">{org.orgNo}</span>
|
|
| 107 |
+ <span className="w-14 shrink-0 text-xs text-gray-500">{org.orgNo}</span>
|
|
| 106 | 108 |
<span className="flex-1 truncate text-sm">{org.orgName}</span>
|
| 107 | 109 |
<StatusBadge status={org.status} />
|
| 108 | 110 |
</button> |
--- frontend/src/components/OrgOverview.test.tsx
+++ frontend/src/components/OrgOverview.test.tsx
... | ... | @@ -33,7 +33,7 @@ |
| 33 | 33 |
function org(overrides: Partial<Org> = {}): Org {
|
| 34 | 34 |
return {
|
| 35 | 35 |
id: 1, |
| 36 |
- orgNo: '001', |
|
| 36 |
+ orgNo: '001_00', |
|
| 37 | 37 |
orgName: '국제방송교류재단', |
| 38 | 38 |
status: 'ACTIVE', |
| 39 | 39 |
applicant: contact({
|
... | ... | @@ -65,7 +65,7 @@ |
| 65 | 65 |
it('연번_기관명 헤더와 신청기관 담당자 정보를 보여준다', async () => {
|
| 66 | 66 |
render(<OrgOverview org={org()} />)
|
| 67 | 67 |
|
| 68 |
- expect(screen.getByText('001_국제방송교류재단')).toBeTruthy()
|
|
| 68 |
+ expect(screen.getByText('001_00_국제방송교류재단')).toBeTruthy()
|
|
| 69 | 69 |
expect(screen.getByText('데이터정보화팀')).toBeTruthy()
|
| 70 | 70 |
expect(screen.getByText('송민지 과장')).toBeTruthy()
|
| 71 | 71 |
expect(screen.getByText('02-3475-5434')).toBeTruthy()
|
... | ... | @@ -170,7 +170,7 @@ |
| 170 | 170 |
const link = screen.getByRole('link', { name: 'Mattermost 열기' })
|
| 171 | 171 |
expect(link).toHaveAttribute( |
| 172 | 172 |
'href', |
| 173 |
- 'https://hub.iten.co.kr/itn-hub/channels/org-001-mj', |
|
| 173 |
+ 'https://hub.iten.co.kr/itn-hub/channels/org-001-00-mj', |
|
| 174 | 174 |
) |
| 175 | 175 |
await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled()) |
| 176 | 176 |
}) |
... | ... | @@ -182,16 +182,16 @@ |
| 182 | 182 |
expect(screen.getByRole('button', { name: 'Mattermost 열기' })).toBeDisabled()
|
| 183 | 183 |
}) |
| 184 | 184 |
|
| 185 |
- it('치안정책연구소는 policy 채널 링크를 쓴다', async () => {
|
|
| 185 |
+ it('치안정책연구소도 합성코드 슬러그로 채널 링크를 만든다', async () => {
|
|
| 186 | 186 |
render( |
| 187 | 187 |
<OrgOverview |
| 188 |
- org={org({ orgNo: '008', orgName: '경찰청_치안정책연구소', channelIdMj: 'x' })}
|
|
| 188 |
+ org={org({ orgNo: '008_01', orgName: '경찰청_치안정책연구소', channelIdMj: 'x' })}
|
|
| 189 | 189 |
/>, |
| 190 | 190 |
) |
| 191 | 191 |
|
| 192 | 192 |
expect(screen.getByRole('link', { name: 'Mattermost 열기' })).toHaveAttribute(
|
| 193 | 193 |
'href', |
| 194 |
- 'https://hub.iten.co.kr/itn-hub/channels/org-008-policy-mj', |
|
| 194 |
+ 'https://hub.iten.co.kr/itn-hub/channels/org-008-01-mj', |
|
| 195 | 195 |
) |
| 196 | 196 |
await waitFor(() => expect(mocks.getPosts).toHaveBeenCalled()) |
| 197 | 197 |
}) |
--- frontend/src/components/OrgOverview.tsx
+++ frontend/src/components/OrgOverview.tsx
... | ... | @@ -31,14 +31,12 @@ |
| 31 | 31 |
|
| 32 | 32 |
// Mattermost 웹 주소. 채널 화면은 팀명 + 채널 내부명으로 열린다. |
| 33 | 33 |
// 내부명 규칙은 백엔드 ChannelNaming.java가 정본이며 여기서는 열람 링크용으로만 복제한다. |
| 34 |
+// 기관 코드({연번1}_{연번2})가 하위기관까지 구분하므로 기관명에 따른 별도 특례는 없다.
|
|
| 34 | 35 |
const MATTERMOST_BASE = 'https://hub.iten.co.kr/itn-hub/channels/' |
| 35 |
-const SPECIAL_ORG_NAME = '경찰청_치안정책연구소' |
|
| 36 | 36 |
|
| 37 | 37 |
function mattermostChannelUrl(org: Org): string {
|
| 38 | 38 |
const slug = org.orgNo.trim().toLowerCase().replace(/_/g, '-').replace(/ /g, '-') |
| 39 |
- const name = |
|
| 40 |
- org.orgName.trim() === SPECIAL_ORG_NAME ? `org-${slug}-policy-mj` : `org-${slug}-mj`
|
|
| 41 |
- return MATTERMOST_BASE + name |
|
| 39 |
+ return MATTERMOST_BASE + `org-${slug}-mj`
|
|
| 42 | 40 |
} |
| 43 | 41 |
|
| 44 | 42 |
function Field({ label, value }: { label: string; value: string | null }) {
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?