}
@@ -220,6 +248,30 @@ class VersionForm extends FormComponent {
+
)
}
diff --git a/src/components/repos/__tests__/versionExpansion.test.js b/src/components/repos/__tests__/versionExpansion.test.js
new file mode 100644
index 000000000..93580a9da
--- /dev/null
+++ b/src/components/repos/__tests__/versionExpansion.test.js
@@ -0,0 +1,50 @@
+import test from 'node:test'
+import assert from 'node:assert/strict'
+
+const {
+ shouldAskForExpansion, shouldShowAutoexpand, getExpansionChoices, getDefaultExpansion, getExpansionPayload
+} = await import('../versionExpansion.js')
+
+const create = {edit: false, isCollection: true}
+const head = '/orgs/MyOrg/collections/MyCollection/HEAD/expansions/autoexpand-HEAD/'
+
+test('with the lock toggle off, creating a version keeps the autoexpand checkbox and asks nothing', () => {
+ const args = {...create, lockToggle: false, headExpansionURL: head}
+ assert.equal(shouldAskForExpansion(args), false)
+ assert.equal(shouldShowAutoexpand(args), true)
+ assert.deepEqual(getExpansionPayload(undefined), {})
+})
+
+test('with the lock toggle on and no HEAD expansion, the choices are latest and none, latest first', () => {
+ const args = {...create, lockToggle: true, headExpansionURL: null}
+ assert.equal(shouldAskForExpansion(args), true)
+ assert.equal(shouldShowAutoexpand(args), false)
+ assert.deepEqual(getExpansionChoices(args), ['latest', 'none'])
+ assert.equal(getDefaultExpansion(args), 'latest')
+})
+
+test('with the lock toggle on and a HEAD expansion, lock is offered and is the default', () => {
+ const args = {...create, lockToggle: true, headExpansionURL: head}
+ assert.deepEqual(getExpansionChoices(args), ['lock', 'latest', 'none'])
+ assert.equal(getDefaultExpansion(args), 'lock')
+})
+
+test('editing a version asks nothing and shows the checkbox, whatever the toggle', () => {
+ for(const lockToggle of [true, false]) {
+ const args = {edit: true, isCollection: true, lockToggle, headExpansionURL: head}
+ assert.equal(shouldAskForExpansion(args), false)
+ assert.equal(shouldShowAutoexpand(args), true)
+ }
+})
+
+test('source versions get neither the popup nor the checkbox', () => {
+ const args = {edit: false, isCollection: false, lockToggle: true, headExpansionURL: head}
+ assert.equal(shouldAskForExpansion(args), false)
+ assert.equal(shouldShowAutoexpand(args), false)
+})
+
+test('each choice maps to its expansion and autoexpand pair', () => {
+ assert.deepEqual(getExpansionPayload('lock'), {expansion: 'lock', autoexpand: true})
+ assert.deepEqual(getExpansionPayload('latest'), {expansion: 'latest', autoexpand: true})
+ assert.deepEqual(getExpansionPayload('none'), {expansion: 'none', autoexpand: false})
+})
diff --git a/src/components/repos/versionExpansion.js b/src/components/repos/versionExpansion.js
new file mode 100644
index 000000000..28ad2c786
--- /dev/null
+++ b/src/components/repos/versionExpansion.js
@@ -0,0 +1,11 @@
+// How a new collection version's expansion is chosen. The popup is asked only with the lock toggle on.
+export const shouldAskForExpansion = ({edit, isCollection, lockToggle}) => Boolean(!edit && isCollection && lockToggle)
+
+export const shouldShowAutoexpand = ({edit, isCollection, lockToggle}) => Boolean(isCollection && (edit || !lockToggle))
+
+export const getExpansionChoices = ({lockToggle, headExpansionURL}) =>
+ lockToggle && headExpansionURL ? ['lock', 'latest', 'none'] : ['latest', 'none']
+
+export const getDefaultExpansion = args => getExpansionChoices(args)[0]
+
+export const getExpansionPayload = expansion => expansion ? {expansion, autoexpand: expansion !== 'none'} : {}
diff --git a/src/i18n/locales/en/translations.json b/src/i18n/locales/en/translations.json
index 651147233..31def3043 100644
--- a/src/i18n/locales/en/translations.json
+++ b/src/i18n/locales/en/translations.json
@@ -770,6 +770,15 @@
"new_title": "New {{resourceType}} Version: {{version}}",
"edit_title": "Edit {{resourceType}} Version: {{version}}"
},
+ "expansion_dialog": {
+ "title": "Expansion for this version",
+ "lock": "Lock repo versions",
+ "lock_help": "Uses the same repository versions as HEAD's expansion. Source versions are saved in the new expansion's parameters, so a rebuild keeps them. Value sets referenced without a version can resolve again on a rebuild.",
+ "latest": "Evaluate from scratch",
+ "latest_help": "Evaluates every reference again. References without a version use each repository's latest released version, or its HEAD if it has no release.",
+ "none": "No expansion",
+ "none_help": "Creates the version without an expansion. You can add one later."
+ },
"update_dialog": {
"title": "Update {{resourceType}}: {{resourceId}}",
"message": "Are you sure you want to {{action}} this {{resourceType}} {{repoId}}?"
diff --git a/src/i18n/locales/es/translations.json b/src/i18n/locales/es/translations.json
index 1cfc61a4c..e8636647e 100644
--- a/src/i18n/locales/es/translations.json
+++ b/src/i18n/locales/es/translations.json
@@ -524,6 +524,15 @@
"form": {
"new_title": "Nueva versión de {{resourceType}}: {{version}}",
"edit_title": "Editar versión de {{resourceType}}: {{version}}"
+ },
+ "expansion_dialog": {
+ "title": "Expansión para esta versión",
+ "lock": "Fijar versiones de repositorio",
+ "lock_help": "Usa las mismas versiones de repositorio que la expansión de HEAD. Las versiones de fuentes se guardan en los parámetros de la nueva expansión, así que una reconstrucción las conserva. Los conjuntos de valores referenciados sin versión pueden resolverse de nuevo al reconstruir.",
+ "latest": "Evaluar desde cero",
+ "latest_help": "Evalúa de nuevo todas las referencias. Las referencias sin versión usan la última versión publicada de cada repositorio, o su HEAD si no tiene ninguna.",
+ "none": "Sin expansión",
+ "none_help": "Crea la versión sin expansión. Puede agregar una más tarde."
}
},
"repo_version": "Versión del repositorio"
diff --git a/src/i18n/locales/pt-BR/translations.json b/src/i18n/locales/pt-BR/translations.json
index 4bc9965f8..99ec7a721 100644
--- a/src/i18n/locales/pt-BR/translations.json
+++ b/src/i18n/locales/pt-BR/translations.json
@@ -759,6 +759,15 @@
"new_title": "Nova versão de {{resourceType}}: {{version}}",
"edit_title": "Editar versão de {{resourceType}}: {{version}}"
},
+ "expansion_dialog": {
+ "title": "Expansão para esta versão",
+ "lock": "Fixar versões de repositório",
+ "lock_help": "Usa as mesmas versões de repositório da expansão do HEAD. As versões de fontes ficam salvas nos parâmetros da nova expansão, então uma reconstrução as mantém. Conjuntos de valores referenciados sem versão podem ser resolvidos de novo ao reconstruir.",
+ "latest": "Avaliar do zero",
+ "latest_help": "Avalia todas as referências novamente. Referências sem versão usam a versão publicada mais recente de cada repositório, ou o HEAD se não houver nenhuma.",
+ "none": "Sem expansão",
+ "none_help": "Cria a versão sem expansão. Você pode adicionar uma depois."
+ },
"update_dialog": {
"title": "Atualizar {{resourceType}}: {{resourceId}}",
"message": "Tem certeza de que deseja {{action}} este {{resourceType}} {{repoId}}?"
diff --git a/src/i18n/locales/zh/translations.json b/src/i18n/locales/zh/translations.json
index 682ba6442..1a0700afd 100644
--- a/src/i18n/locales/zh/translations.json
+++ b/src/i18n/locales/zh/translations.json
@@ -553,6 +553,15 @@
"form": {
"new_title": "新建{{resourceType}}版本:{{version}}",
"edit_title": "编辑{{resourceType}}版本:{{version}}"
+ },
+ "expansion_dialog": {
+ "title": "此版本的扩展",
+ "lock": "锁定存储库版本",
+ "lock_help": "使用与 HEAD 扩展相同的存储库版本。源版本保存在新扩展的参数中,因此重建会保留它们。未指定版本引用的值集在重建时可能会重新解析。",
+ "latest": "从头评估",
+ "latest_help": "重新评估每个引用。没有版本的引用使用每个存储库最新发布的版本;如果没有发布版本,则使用其 HEAD。",
+ "none": "不扩展",
+ "none_help": "创建不带扩展的版本。之后可以再添加。"
}
},
"repo_version": "仓库版本"