Skip to content

Commit 566bf6a

Browse files
yazzylazyclaude
andcommitted
Address Marcella's review: centralize strings, prune tests, drop Public toggle
Per review feedback: - All $trs blocks across the 8 Organization components are consolidated into shared/strings/organizationStrings.js (createTranslator pattern, matching shared/strings/searchRecommendationsStrings.js), so translators work from one file instead of eight, and adjusting wording pre-release no longer means finding it scattered across components. - Removes the "Public" checkbox and all related code from OrganizationDetailsTab (isPublic state, the organization.public watch, the public field in the save payload). Nothing else in the feature reads organization.public, and there's no browsable-organizations page for it to matter to yet. The backend public field defaults to False, so omitting it from the payload is a no-op there. - Removed 6 tests whose assertions were already implied by a stronger neighboring test in the same file (a shallow "emits an event" or "renders initial state" check subsumed by the full interaction/ end-to-end test right next to it), plus both tests in OrganizationSharingTab.spec.js (pure text-presence checks with no interaction, and the file is deleted since nothing remains). One unique assertion (no Sharing tab while creating) was folded into the test that already covers the rest of that flow. - Updated the remaining tests to assert against organizationStrings references instead of hardcoded literal UI text, so a wording tweak during translation prep doesn't silently break test coverage. Test fixture data (org names, emails made up for a test) stays literal, per the same guidance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 17f2865 commit 566bf6a

16 files changed

Lines changed: 439 additions & 360 deletions

‎contentcuration/contentcuration/frontend/channelList/views/Organization/InviteOrganizationUserForm.vue‎

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<template>
22

33
<div class="invite-organization-user-form">
4-
<h2>{{ $tr('inviteUsers') }}</h2>
4+
<h2>{{ organizationStrings.inviteUsers$() }}</h2>
55

66
<div class="fields">
77
<KTextbox
88
v-model="email"
99
type="email"
1010
data-test="email-input"
11-
:label="$tr('emailLabel')"
11+
:label="organizationStrings.emailLabel$()"
1212
:invalid="Boolean(emailError)"
1313
:invalidText="emailError"
1414
:showInvalidText="Boolean(emailError)"
@@ -17,15 +17,15 @@
1717
<KSelect
1818
v-model="role"
1919
data-test="role-select"
20-
:label="$tr('roleLabel')"
20+
:label="organizationStrings.roleLabel$()"
2121
:options="roleOptions"
2222
/>
2323
</div>
2424

2525
<KButton
2626
appearance="raised-button"
2727
primary
28-
:text="$tr('sendInvitation')"
28+
:text="organizationStrings.sendInvitation$()"
2929
:disabled="sending"
3030
@click="submit"
3131
/>
@@ -38,13 +38,14 @@
3838
3939
import { InvitationShareModes } from '../../constants';
4040
import { getApiErrorMessage } from '../../utils';
41+
import { organizationStrings } from 'shared/strings/organizationStrings';
4142
import useSnackbar from 'shared/composables/useSnackbar';
4243
4344
export default {
4445
name: 'InviteOrganizationUserForm',
4546
setup() {
4647
const { createSnackbar } = useSnackbar();
47-
return { createSnackbar };
48+
return { createSnackbar, organizationStrings };
4849
},
4950
props: {
5051
organizationId: {
@@ -67,9 +68,9 @@
6768
computed: {
6869
roleOptions() {
6970
return [
70-
{ label: this.$tr('viewerRole'), value: InvitationShareModes.VIEW_ONLY },
71-
{ label: this.$tr('editorRole'), value: InvitationShareModes.EDIT },
72-
{ label: this.$tr('adminRole'), value: InvitationShareModes.ADMIN },
71+
{ label: organizationStrings.viewerRole$(), value: InvitationShareModes.VIEW_ONLY },
72+
{ label: organizationStrings.editorRole$(), value: InvitationShareModes.EDIT },
73+
{ label: organizationStrings.adminRole$(), value: InvitationShareModes.ADMIN },
7374
];
7475
},
7576
},
@@ -80,7 +81,7 @@
8081
submit() {
8182
const email = this.email.trim();
8283
if (!email) {
83-
this.emailError = this.$tr('emailRequired');
84+
this.emailError = organizationStrings.emailRequired$();
8485
return;
8586
}
8687
this.sending = true;
@@ -92,28 +93,16 @@
9293
.then(() => {
9394
this.email = '';
9495
this.role = this.roleOptions[0];
95-
this.createSnackbar(this.$tr('invitationSent'));
96+
this.createSnackbar(organizationStrings.invitationSent$());
9697
})
9798
.catch(error => {
98-
this.createSnackbar(getApiErrorMessage(error, this.$tr('invitationError')));
99+
this.createSnackbar(getApiErrorMessage(error, organizationStrings.invitationError$()));
99100
})
100101
.finally(() => {
101102
this.sending = false;
102103
});
103104
},
104105
},
105-
$trs: {
106-
inviteUsers: 'Invite users',
107-
emailLabel: 'Email',
108-
emailRequired: 'Email is required',
109-
roleLabel: 'Role type',
110-
viewerRole: 'Viewer',
111-
editorRole: 'Editor',
112-
adminRole: 'Admin',
113-
sendInvitation: 'Send invitation',
114-
invitationSent: 'Invitation sent',
115-
invitationError: 'Unable to send this invitation',
116-
},
117106
};
118107
119108
</script>

‎contentcuration/contentcuration/frontend/channelList/views/Organization/OrganizationCard.vue‎

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<KIconButton
3737
icon="optionsVertical"
3838
appearance="flat-button"
39-
:ariaLabel="$tr('moreOptions', { name: organization.name })"
39+
:ariaLabel="organizationStrings.moreOptions$({ name: organization.name })"
4040
data-test="organization-options"
4141
@click.stop
4242
>
@@ -57,6 +57,7 @@
5757
<script>
5858
5959
import { OrganizationRoles, OrganizationEditTabs, RouteNames } from '../../constants';
60+
import { organizationStrings } from 'shared/strings/organizationStrings';
6061
6162
export default {
6263
name: 'OrganizationCard',
@@ -70,17 +71,20 @@
7071
required: true,
7172
},
7273
},
74+
data() {
75+
return { organizationStrings };
76+
},
7377
computed: {
7478
roleLabel() {
7579
const labels = {
76-
[OrganizationRoles.ADMIN]: this.$tr('adminRole'),
77-
[OrganizationRoles.EDITOR]: this.$tr('editorRole'),
78-
[OrganizationRoles.VIEWER]: this.$tr('viewerRole'),
80+
[OrganizationRoles.ADMIN]: organizationStrings.adminRole$(),
81+
[OrganizationRoles.EDITOR]: organizationStrings.editorRole$(),
82+
[OrganizationRoles.VIEWER]: organizationStrings.viewerRole$(),
7983
};
8084
return labels[this.organization.role] || '';
8185
},
8286
dropdownOptions() {
83-
return [{ label: this.$tr('editOrganization'), icon: 'edit', value: 'edit' }];
87+
return [{ label: organizationStrings.editOrganization$(), icon: 'edit', value: 'edit' }];
8488
},
8589
},
8690
methods: {
@@ -94,13 +98,6 @@
9498
}
9599
},
96100
},
97-
$trs: {
98-
adminRole: 'Admin',
99-
editorRole: 'Editor',
100-
viewerRole: 'Viewer',
101-
moreOptions: 'More options for {name}',
102-
editOrganization: 'Edit organization',
103-
},
104101
};
105102
106103
</script>

‎contentcuration/contentcuration/frontend/channelList/views/Organization/OrganizationDetailsTab.vue‎

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@
1717
/>
1818
</span>
1919

20-
<h2>{{ $tr('organizationDetails') }}</h2>
20+
<h2>{{ organizationStrings.organizationDetails$() }}</h2>
2121

2222
<p
2323
v-if="!isAdmin"
2424
class="view-only-notice"
2525
>
26-
{{ $tr('viewOnlyNotice') }}
26+
{{ organizationStrings.adminAccessRequiredForEdits$() }}
2727
</p>
2828

2929
<KTextbox
3030
v-model="name"
3131
data-test="name-input"
32-
:label="$tr('nameLabel')"
32+
:label="organizationStrings.nameLabel$()"
3333
:maxlength="200"
3434
:disabled="!isAdmin"
3535
:invalid="Boolean(nameError)"
@@ -42,26 +42,17 @@
4242
v-model="description"
4343
data-test="description-input"
4444
textArea
45-
:label="$tr('descriptionLabel')"
45+
:label="organizationStrings.descriptionLabel$()"
4646
:disabled="!isAdmin"
4747
style="margin-top: 16px"
4848
/>
4949

50-
<KCheckbox
51-
:checked="isPublic"
52-
:label="$tr('publicLabel')"
53-
:description="$tr('publicDescription')"
54-
:disabled="!isAdmin"
55-
style="margin-top: 16px"
56-
@change="value => (isPublic = value)"
57-
/>
58-
5950
<KButton
6051
v-if="isAdmin"
6152
appearance="raised-button"
6253
primary
6354
class="save-button"
64-
:text="isNew ? $tr('createOrganization') : $tr('saveChanges')"
55+
:text="isNew ? organizationStrings.createOrganization$() : organizationStrings.saveChanges$()"
6556
:disabled="saving"
6657
@click="submit"
6758
/>
@@ -74,13 +65,14 @@
7465
<script>
7566
7667
import { getApiErrorMessage } from '../../utils';
68+
import { organizationStrings } from 'shared/strings/organizationStrings';
7769
import useSnackbar from 'shared/composables/useSnackbar';
7870
7971
export default {
8072
name: 'OrganizationDetailsTab',
8173
setup() {
8274
const { createSnackbar } = useSnackbar();
83-
return { createSnackbar };
75+
return { createSnackbar, organizationStrings };
8476
},
8577
props: {
8678
organization: {
@@ -108,7 +100,6 @@
108100
return {
109101
name: '',
110102
description: '',
111-
isPublic: false,
112103
nameError: '',
113104
saving: false,
114105
};
@@ -120,53 +111,37 @@
120111
if (organization) {
121112
this.name = organization.name || '';
122113
this.description = organization.description || '';
123-
this.isPublic = Boolean(organization.public);
124114
}
125115
},
126116
},
127117
},
128118
methods: {
129119
submit() {
130120
if (!this.name.trim()) {
131-
this.nameError = this.$tr('nameRequired');
121+
this.nameError = organizationStrings.nameRequired$();
132122
return;
133123
}
134124
this.saving = true;
135125
this.save({
136126
name: this.name.trim(),
137127
description: this.description.trim(),
138-
public: this.isPublic,
139128
})
140129
.then(organization => {
141130
if (this.isNew) {
142-
this.createSnackbar(this.$tr('organizationCreated'));
131+
this.createSnackbar(organizationStrings.organizationCreated$());
143132
this.$emit('created', organization.id);
144133
} else {
145-
this.createSnackbar(this.$tr('changesSaved'));
134+
this.createSnackbar(organizationStrings.changesSaved$());
146135
}
147136
})
148137
.catch(error => {
149-
this.createSnackbar(getApiErrorMessage(error, this.$tr('saveError')));
138+
this.createSnackbar(getApiErrorMessage(error, organizationStrings.saveError$()));
150139
})
151140
.finally(() => {
152141
this.saving = false;
153142
});
154143
},
155144
},
156-
$trs: {
157-
organizationDetails: 'Organization details',
158-
nameLabel: 'Organization name',
159-
descriptionLabel: 'Organization description',
160-
nameRequired: 'Organization name is required',
161-
viewOnlyNotice: 'Only organization admins can edit these details.',
162-
publicLabel: 'Public',
163-
publicDescription: 'If this organization can be seen by users outside the organization',
164-
saveChanges: 'Save changes',
165-
createOrganization: 'Create organization',
166-
changesSaved: 'Changes saved',
167-
organizationCreated: 'Organization created',
168-
saveError: 'Unable to save these changes',
169-
},
170145
};
171146
172147
</script>

‎contentcuration/contentcuration/frontend/channelList/views/Organization/OrganizationEditPage.vue‎

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
>
77
<template #header>
88
<span class="notranslate">
9-
{{ isNew ? $tr('newOrganizationTitle') : organization ? organization.name : '' }}
9+
{{ isNew ? organizationStrings.newOrganizationTitle$() : organization ? organization.name : '' }}
1010
</span>
1111
</template>
1212

@@ -18,7 +18,7 @@
1818
tabsId="organization-edit-tabs"
1919
:tabs="tabs"
2020
:activeTabId="tab"
21-
:ariaLabel="$tr('tabsLabel')"
21+
:ariaLabel="organizationStrings.tabsLabel$()"
2222
/>
2323
</nav>
2424

@@ -62,6 +62,7 @@
6262
import { useOrganization } from '../../composables/useOrganization';
6363
import OrganizationDetailsTab from './OrganizationDetailsTab.vue';
6464
import OrganizationSharingTab from './OrganizationSharingTab.vue';
65+
import { organizationStrings } from 'shared/strings/organizationStrings';
6566
import { routerMixin } from 'shared/mixins';
6667
import StudioImmersiveModal from 'shared/views/StudioImmersiveModal';
6768
@@ -82,6 +83,7 @@
8283
update,
8384
create,
8485
tabIds: OrganizationEditTabs,
86+
organizationStrings,
8587
};
8688
},
8789
props: {
@@ -113,12 +115,12 @@
113115
return [
114116
{
115117
id: OrganizationEditTabs.DETAILS,
116-
label: this.$tr('detailsTab'),
118+
label: organizationStrings.detailsTab$(),
117119
to: this.tabLink(OrganizationEditTabs.DETAILS),
118120
},
119121
{
120122
id: OrganizationEditTabs.SHARING,
121-
label: this.$tr('sharingTab'),
123+
label: organizationStrings.sharingTab$(),
122124
to: this.tabLink(OrganizationEditTabs.SHARING),
123125
},
124126
];
@@ -170,23 +172,17 @@
170172
},
171173
updateTitle() {
172174
if (this.isNew) {
173-
this.updateTabTitle(this.$tr('newOrganizationTitle'));
175+
this.updateTabTitle(organizationStrings.newOrganizationTitle$());
174176
return;
175177
}
176178
const orgName = this.organization ? this.organization.name : '';
177179
const tabLabel =
178180
this.tab === OrganizationEditTabs.SHARING
179-
? this.$tr('sharingTab')
180-
: this.$tr('detailsTab');
181+
? organizationStrings.sharingTab$()
182+
: organizationStrings.detailsTab$();
181183
this.updateTabTitle(orgName ? `${tabLabel} - ${orgName}` : tabLabel);
182184
},
183185
},
184-
$trs: {
185-
tabsLabel: 'Organization edit tabs',
186-
detailsTab: 'Details',
187-
sharingTab: 'Sharing',
188-
newOrganizationTitle: 'New organization',
189-
},
190186
};
191187
192188
</script>

0 commit comments

Comments
 (0)