mirror of
https://github.com/logto-io/logto.git
synced 2025-04-07 23:01:25 -05:00
feat(console): add protected app creation form (#5228)
* feat(console): add protected app creation form * refactor(console): use whitelist to display application types in app creation form
This commit is contained in:
parent
cbfd00e673
commit
d506f94c18
58 changed files with 1287 additions and 25 deletions
41
packages/console/src/assets/icons/protected-app-dark.svg
Normal file
41
packages/console/src/assets/icons/protected-app-dark.svg
Normal file
|
@ -0,0 +1,41 @@
|
|||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="40" height="40" rx="8" fill="#F7F8F8" fill-opacity="0.12"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M30.7059 9.90131C31.0085 9.90758 31.255 10.1523 31.255 10.4549V22.9302C31.255 27.4132 25.5194 32.5261 20.3161 33.9324C20.1444 33.9788 19.9656 33.9788 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515C19.8064 6.34313 20.3035 6.34313 20.5808 6.61514C21.9312 7.93967 25.1542 9.7863 30.7059 9.90131ZM22.3817 17.7052C22.3817 18.6191 21.8272 19.4031 21.037 19.7376L22.1889 22.7375C22.3301 23.1051 22.0587 23.5 21.6649 23.5H18.382C17.9667 23.5 17.6952 23.0645 17.8781 22.6916L19.3264 19.7376C18.5362 19.4031 17.9817 18.6191 17.9817 17.7052C17.9817 16.4873 18.9667 15.5 20.1817 15.5C21.3967 15.5 22.3817 16.4873 22.3817 17.7052Z" fill="url(#paint0_linear_10098_21308)"/>
|
||||
<mask id="path-3-inside-1_10098_21308" fill="white">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5291 6.61515C19.6678 6.47915 19.8613 6.41114 20.0549 6.41113V15.5036C18.8989 15.5694 17.9817 16.53 17.9817 17.7052C17.9817 18.6191 18.5362 19.4031 19.3264 19.7376L17.8781 22.6916C17.6952 23.0645 17.9667 23.5 18.382 23.5H20.0549V33.9672C19.9673 33.9672 19.8797 33.9556 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515Z"/>
|
||||
</mask>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5291 6.61515C19.6678 6.47915 19.8613 6.41114 20.0549 6.41113V15.5036C18.8989 15.5694 17.9817 16.53 17.9817 17.7052C17.9817 18.6191 18.5362 19.4031 19.3264 19.7376L17.8781 22.6916C17.6952 23.0645 17.9667 23.5 18.382 23.5H20.0549V33.9672C19.9673 33.9672 19.8797 33.9556 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515Z" fill="url(#paint1_linear_10098_21308)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5291 6.61515C19.6678 6.47915 19.8613 6.41114 20.0549 6.41113V15.5036C18.8989 15.5694 17.9817 16.53 17.9817 17.7052C17.9817 18.6191 18.5362 19.4031 19.3264 19.7376L17.8781 22.6916C17.6952 23.0645 17.9667 23.5 18.382 23.5H20.0549V33.9672C19.9673 33.9672 19.8797 33.9556 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515Z" fill="#4300DA"/>
|
||||
<path d="M20.0549 6.41113H33.315V-6.84972L20.0541 -6.84891L20.0549 6.41113ZM19.5291 6.61515L28.8145 16.0815L28.8145 16.0815L19.5291 6.61515ZM20.0549 15.5036L20.8088 28.7422L33.315 28.0301V15.5036H20.0549ZM19.3264 19.7376L31.2324 25.5751L37.4022 12.991L24.4961 7.52687L19.3264 19.7376ZM17.8781 22.6916L29.784 28.529L29.7841 28.529L17.8781 22.6916ZM20.0549 23.5H33.315V10.24H20.0549V23.5ZM20.0549 33.9672L20.0544 47.2273L33.315 47.2279V33.9672H20.0549ZM19.7939 33.9324L23.2536 21.1317L23.2535 21.1317L19.7939 33.9324ZM9.40402 9.90131L9.12938 -3.35589H9.12938L9.40402 9.90131ZM20.0541 -6.84891C16.9088 -6.84872 13.2095 -5.76016 10.2438 -2.85116L28.8145 16.0815C26.1261 18.7185 22.8139 19.671 20.0557 19.6712L20.0541 -6.84891ZM33.315 15.5036V6.41113H6.79489V15.5036H33.315ZM19.3011 2.265C11.1389 2.72977 4.72165 9.4865 4.72165 17.7052H31.2417C31.2417 23.5734 26.6589 28.4091 20.8088 28.7422L19.3011 2.265ZM4.72165 17.7052C4.72165 24.1163 8.62235 29.6053 14.1566 31.9484L24.4961 7.52687C28.4501 9.20089 31.2417 13.1218 31.2417 17.7052H4.72165ZM7.42036 13.9002L5.97205 16.8541L29.7841 28.529L31.2324 25.5751L7.42036 13.9002ZM5.97205 16.8541C1.46958 26.0373 8.15456 36.76 18.382 36.76V10.24C27.7788 10.24 33.9208 20.0917 29.784 28.529L5.97205 16.8541ZM18.382 36.76H20.0549V10.24H18.382V36.76ZM33.315 33.9672V23.5H6.79489V33.9672H33.315ZM16.3342 46.7332C17.5424 47.0597 18.7929 47.2272 20.0544 47.2273L20.0555 20.7072C21.1417 20.7072 22.2171 20.8515 23.2536 21.1317L16.3342 46.7332ZM-4.40506 22.9302C-4.40506 30.4476 0.0177698 36.0848 3.15823 39.1199C6.64011 42.485 11.2987 45.3723 16.3343 46.7332L23.2535 21.1317C23.2665 21.1352 23.0247 21.0637 22.6154 20.8228C22.2189 20.5895 21.8548 20.3079 21.5882 20.0503C21.3006 19.7723 21.3185 19.71 21.466 19.9797C21.5968 20.2188 22.115 21.2481 22.115 22.9302H-4.40506ZM-4.40506 10.4549V22.9302H22.115V10.4549H-4.40506ZM9.12938 -3.35589C1.82644 -3.2046 -4.40506 2.72348 -4.40506 10.4549H22.115C22.115 17.5811 16.3765 23.0198 9.67866 23.1585L9.12938 -3.35589ZM10.2438 -2.85118C10.6661 -3.26546 10.9893 -3.48532 11.1382 -3.57823C11.302 -3.68044 11.3593 -3.69411 11.2829 -3.66475C11.1448 -3.61165 10.4791 -3.38385 9.12938 -3.35589L9.67865 23.1585C17.9921 22.9863 24.647 20.1693 28.8145 16.0815L10.2438 -2.85118Z" fill="#9C85FD" mask="url(#path-3-inside-1_10098_21308)"/>
|
||||
<rect x="4" y="24" width="3" height="3" rx="0.5" fill="url(#paint2_linear_10098_21308)"/>
|
||||
<rect x="4" y="12" width="3" height="3" rx="0.5" fill="url(#paint3_linear_10098_21308)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.229 21.3673C12.3535 21.2409 12.2639 21.027 12.0865 21.027L4.50936 21.0269C4.23155 21.0269 4.00635 20.8017 4.00635 20.5239L4.00635 18.4188C4.00635 18.141 4.23156 17.9158 4.50937 17.9158L12.0802 17.9159C12.2585 17.9159 12.3477 17.7002 12.2214 17.5743L10.497 15.8552C10.181 15.5401 10.4046 15.0003 10.8509 15.0011L12.7032 15.0042C12.9827 15.0047 13.2492 15.1221 13.4382 15.3281L16.8613 19.0576C17.1472 19.3691 17.1413 19.8493 16.8479 20.1537L13.4367 23.6929C13.2482 23.8884 12.9883 23.9989 12.7167 23.9989L10.8321 23.999C10.3885 23.999 10.1646 23.4643 10.4758 23.1482L12.229 21.3673Z" fill="#F7F8F8" fill-opacity="0.14"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.229 21.3673C12.3535 21.2409 12.2639 21.027 12.0865 21.027L4.50936 21.0269C4.23155 21.0269 4.00635 20.8017 4.00635 20.5239L4.00635 18.4188C4.00635 18.141 4.23156 17.9158 4.50937 17.9158L12.0802 17.9159C12.2585 17.9159 12.3477 17.7002 12.2214 17.5743L10.497 15.8552C10.181 15.5401 10.4046 15.0003 10.8509 15.0011L12.7032 15.0042C12.9827 15.0047 13.2492 15.1221 13.4382 15.3281L16.8613 19.0576C17.1472 19.3691 17.1413 19.8493 16.8479 20.1537L13.4367 23.6929C13.2482 23.8884 12.9883 23.9989 12.7167 23.9989L10.8321 23.999C10.3885 23.999 10.1646 23.4643 10.4758 23.1482L12.229 21.3673Z" fill="url(#paint4_linear_10098_21308)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.229 21.3673C12.3535 21.2409 12.2639 21.027 12.0865 21.027L4.50936 21.0269C4.23155 21.0269 4.00635 20.8017 4.00635 20.5239L4.00635 18.4188C4.00635 18.141 4.23156 17.9158 4.50937 17.9158L12.0802 17.9159C12.2585 17.9159 12.3477 17.7002 12.2214 17.5743L10.497 15.8552C10.181 15.5401 10.4046 15.0003 10.8509 15.0011L12.7032 15.0042C12.9827 15.0047 13.2492 15.1221 13.4382 15.3281L16.8613 19.0576C17.1472 19.3691 17.1413 19.8493 16.8479 20.1537L13.4367 23.6929C13.2482 23.8884 12.9883 23.9989 12.7167 23.9989L10.8321 23.999C10.3885 23.999 10.1646 23.4643 10.4758 23.1482L12.229 21.3673Z" fill="url(#paint5_linear_10098_21308)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_10098_21308" x1="7.01498" y1="22.0417" x2="32.0378" y2="14.6503" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#492EF3"/>
|
||||
<stop offset="1" stop-color="#CF69FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_10098_21308" x1="7.93498" y1="22.1985" x2="21.2384" y2="20.202" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#492EF3"/>
|
||||
<stop offset="1" stop-color="#CF69FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_10098_21308" x1="10.724" y1="24.7014" x2="1.45582" y2="26.3359" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF06A"/>
|
||||
<stop offset="1" stop-color="#EC78FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_10098_21308" x1="10.724" y1="12.7014" x2="1.45582" y2="14.3359" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF06A"/>
|
||||
<stop offset="1" stop-color="#EC78FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_10098_21308" x1="-13.3667" y1="22.3616" x2="17.5959" y2="13.6301" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF06A"/>
|
||||
<stop offset="1" stop-color="#EC78FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_10098_21308" x1="-1.89633" y1="23.0299" x2="26.2046" y2="13.1434" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EC78FF"/>
|
||||
<stop offset="1" stop-color="#FFF06A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 8.2 KiB |
37
packages/console/src/assets/icons/protected-app.svg
Normal file
37
packages/console/src/assets/icons/protected-app.svg
Normal file
|
@ -0,0 +1,37 @@
|
|||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="40" height="40" rx="8" fill="#F3EFFA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M30.7059 9.90131C31.0085 9.90758 31.255 10.1523 31.255 10.4549V22.9302C31.255 27.4132 25.5194 32.5261 20.3161 33.9324C20.1444 33.9788 19.9656 33.9788 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515C19.8064 6.34313 20.3035 6.34313 20.5808 6.61514C21.9312 7.93967 25.1542 9.7863 30.7059 9.90131ZM22.3817 17.7052C22.3817 18.6191 21.8272 19.4031 21.037 19.7376L22.1889 22.7375C22.3301 23.1051 22.0587 23.5 21.6649 23.5H18.382C17.9667 23.5 17.6952 23.0645 17.8781 22.6916L19.3264 19.7376C18.5362 19.4031 17.9817 18.6191 17.9817 17.7052C17.9817 16.4873 18.9667 15.5 20.1817 15.5C21.3967 15.5 22.3817 16.4873 22.3817 17.7052Z" fill="url(#paint0_linear_10098_21288)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5291 6.61515C19.6678 6.47915 19.8613 6.41114 20.0549 6.41113V15.5036C18.8989 15.5694 17.9817 16.53 17.9817 17.7052C17.9817 18.6191 18.5362 19.4031 19.3264 19.7376L17.8781 22.6916C17.6952 23.0645 17.9667 23.5 18.382 23.5H20.0549V33.9672C19.9673 33.9672 19.8797 33.9556 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515Z" fill="url(#paint1_linear_10098_21288)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5291 6.61515C19.6678 6.47915 19.8613 6.41114 20.0549 6.41113V15.5036C18.8989 15.5694 17.9817 16.53 17.9817 17.7052C17.9817 18.6191 18.5362 19.4031 19.3264 19.7376L17.8781 22.6916C17.6952 23.0645 17.9667 23.5 18.382 23.5H20.0549V33.9672C19.9673 33.9672 19.8797 33.9556 19.7939 33.9324C14.5906 32.5261 8.85498 27.4132 8.85498 22.9302V10.4549C8.85498 10.1523 9.10147 9.90758 9.40402 9.90131C14.9558 9.7863 18.1788 7.93967 19.5291 6.61515Z" fill="#4300DA"/>
|
||||
<rect x="4" y="24" width="3" height="3" rx="0.5" fill="url(#paint2_linear_10098_21288)"/>
|
||||
<rect x="4" y="12" width="3" height="3" rx="0.5" fill="url(#paint3_linear_10098_21288)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.229 21.3673C12.3535 21.2409 12.2639 21.027 12.0865 21.027L4.50936 21.0269C4.23155 21.0269 4.00635 20.8017 4.00635 20.5239L4.00635 18.4188C4.00635 18.141 4.23156 17.9158 4.50937 17.9158L12.0802 17.9159C12.2585 17.9159 12.3477 17.7002 12.2214 17.5743L10.497 15.8552C10.181 15.5401 10.4046 15.0003 10.8509 15.0011L12.7032 15.0042C12.9827 15.0047 13.2492 15.1221 13.4382 15.3281L16.8613 19.0576C17.1472 19.3691 17.1413 19.8493 16.8479 20.1537L13.4367 23.6929C13.2482 23.8884 12.9883 23.9989 12.7167 23.9989L10.8321 23.999C10.3885 23.999 10.1646 23.4643 10.4758 23.1482L12.229 21.3673Z" fill="#191C1D" fill-opacity="0.12"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.229 21.3673C12.3535 21.2409 12.2639 21.027 12.0865 21.027L4.50936 21.0269C4.23155 21.0269 4.00635 20.8017 4.00635 20.5239L4.00635 18.4188C4.00635 18.141 4.23156 17.9158 4.50937 17.9158L12.0802 17.9159C12.2585 17.9159 12.3477 17.7002 12.2214 17.5743L10.497 15.8552C10.181 15.5401 10.4046 15.0003 10.8509 15.0011L12.7032 15.0042C12.9827 15.0047 13.2492 15.1221 13.4382 15.3281L16.8613 19.0576C17.1472 19.3691 17.1413 19.8493 16.8479 20.1537L13.4367 23.6929C13.2482 23.8884 12.9883 23.9989 12.7167 23.9989L10.8321 23.999C10.3885 23.999 10.1646 23.4643 10.4758 23.1482L12.229 21.3673Z" fill="url(#paint4_linear_10098_21288)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.229 21.3673C12.3535 21.2409 12.2639 21.027 12.0865 21.027L4.50936 21.0269C4.23155 21.0269 4.00635 20.8017 4.00635 20.5239L4.00635 18.4188C4.00635 18.141 4.23156 17.9158 4.50937 17.9158L12.0802 17.9159C12.2585 17.9159 12.3477 17.7002 12.2214 17.5743L10.497 15.8552C10.181 15.5401 10.4046 15.0003 10.8509 15.0011L12.7032 15.0042C12.9827 15.0047 13.2492 15.1221 13.4382 15.3281L16.8613 19.0576C17.1472 19.3691 17.1413 19.8493 16.8479 20.1537L13.4367 23.6929C13.2482 23.8884 12.9883 23.9989 12.7167 23.9989L10.8321 23.999C10.3885 23.999 10.1646 23.4643 10.4758 23.1482L12.229 21.3673Z" fill="url(#paint5_linear_10098_21288)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_10098_21288" x1="7.01498" y1="22.0417" x2="32.0378" y2="14.6503" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#492EF3"/>
|
||||
<stop offset="1" stop-color="#CF69FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_10098_21288" x1="7.93498" y1="22.1985" x2="21.2384" y2="20.202" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#492EF3"/>
|
||||
<stop offset="1" stop-color="#CF69FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_10098_21288" x1="10.724" y1="24.7014" x2="1.45582" y2="26.3359" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF06A"/>
|
||||
<stop offset="1" stop-color="#EC78FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_10098_21288" x1="10.724" y1="12.7014" x2="1.45582" y2="14.3359" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF06A"/>
|
||||
<stop offset="1" stop-color="#EC78FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_10098_21288" x1="-13.3667" y1="22.3616" x2="17.5959" y2="13.6301" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF06A"/>
|
||||
<stop offset="1" stop-color="#EC78FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_10098_21288" x1="-1.89633" y1="23.0299" x2="26.2046" y2="13.1434" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EC78FF"/>
|
||||
<stop offset="1" stop-color="#FFF06A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 5.4 KiB |
|
@ -4,6 +4,8 @@ import MachineToMachineDark from '@/assets/icons/machine-to-machine-dark.svg';
|
|||
import MachineToMachine from '@/assets/icons/machine-to-machine.svg';
|
||||
import NativeAppDark from '@/assets/icons/native-app-dark.svg';
|
||||
import NativeApp from '@/assets/icons/native-app.svg';
|
||||
import ProtectedAppDark from '@/assets/icons/protected-app-dark.svg';
|
||||
import ProtectedApp from '@/assets/icons/protected-app.svg';
|
||||
import SinglePageAppDark from '@/assets/icons/single-page-app-dark.svg';
|
||||
import SinglePageApp from '@/assets/icons/single-page-app.svg';
|
||||
import TraditionalWebAppDark from '@/assets/icons/traditional-web-app-dark.svg';
|
||||
|
@ -18,8 +20,7 @@ export const lightModeApplicationIconMap: ApplicationIconMap = Object.freeze({
|
|||
[ApplicationType.SPA]: SinglePageApp,
|
||||
[ApplicationType.Traditional]: TraditionalWebApp,
|
||||
[ApplicationType.MachineToMachine]: MachineToMachine,
|
||||
// TODO @sijie: update with new icon
|
||||
[ApplicationType.Protected]: TraditionalWebApp,
|
||||
[ApplicationType.Protected]: ProtectedApp,
|
||||
} as const);
|
||||
|
||||
export const darkModeApplicationIconMap: ApplicationIconMap = Object.freeze({
|
||||
|
@ -27,6 +28,5 @@ export const darkModeApplicationIconMap: ApplicationIconMap = Object.freeze({
|
|||
[ApplicationType.SPA]: SinglePageAppDark,
|
||||
[ApplicationType.Traditional]: TraditionalWebAppDark,
|
||||
[ApplicationType.MachineToMachine]: MachineToMachineDark,
|
||||
// TODO @sijie: update with new icon
|
||||
[ApplicationType.Protected]: TraditionalWebAppDark,
|
||||
[ApplicationType.Protected]: ProtectedAppDark,
|
||||
} as const);
|
||||
|
|
|
@ -5,7 +5,6 @@ import { toast } from 'react-hot-toast';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
import { isDevFeaturesEnabled } from '@/consts/env';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
|
@ -111,7 +110,15 @@ function CreateForm({
|
|||
onChange={onChange}
|
||||
>
|
||||
{Object.values(ApplicationType)
|
||||
.filter((value) => isDevFeaturesEnabled || value !== ApplicationType.Protected)
|
||||
// Other application types (e.g. "Protected") should not show up in the creation modal
|
||||
.filter((value) =>
|
||||
[
|
||||
ApplicationType.Native,
|
||||
ApplicationType.SPA,
|
||||
ApplicationType.Traditional,
|
||||
ApplicationType.MachineToMachine,
|
||||
].includes(value)
|
||||
)
|
||||
.map((type) => (
|
||||
<Radio
|
||||
key={type}
|
||||
|
|
|
@ -19,6 +19,7 @@ import { allAppGuideCategories, type AppGuideCategory } from '@/types/applicatio
|
|||
import { thirdPartyAppCategory } from '@/types/applications';
|
||||
|
||||
import CreateForm from '../CreateForm';
|
||||
import ProtectedAppCard from '../ProtectedAppCard';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -95,8 +96,8 @@ function GuideLibrary({ className, hasCardBorder, hasCardButton, hasFilters }: P
|
|||
options={allAppGuideCategories
|
||||
.filter(
|
||||
(category) =>
|
||||
isDevFeaturesEnabled ||
|
||||
(category !== 'Protected' && category !== thirdPartyAppCategory)
|
||||
category !== 'Protected' &&
|
||||
(isDevFeaturesEnabled || category !== thirdPartyAppCategory)
|
||||
)
|
||||
.map((category) => ({
|
||||
title: `guide.categories.${category}`,
|
||||
|
@ -135,21 +136,25 @@ function GuideLibrary({ className, hasCardBorder, hasCardButton, hasFilters }: P
|
|||
) : (
|
||||
<EmptyDataPlaceholder className={styles.emptyPlaceholder} size="large" />
|
||||
))}
|
||||
{!keyword &&
|
||||
(filterCategories.length > 0 ? filterCategories : allAppGuideCategories).map(
|
||||
(category) =>
|
||||
structuredMetadata[category].length > 0 && (
|
||||
<GuideCardGroup
|
||||
key={category}
|
||||
className={styles.guideGroup}
|
||||
hasCardBorder={hasCardBorder}
|
||||
hasCardButton={hasCardButton}
|
||||
categoryName={t(`categories.${category}`)}
|
||||
guides={structuredMetadata[category]}
|
||||
onClickGuide={onClickGuide}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{!keyword && (
|
||||
<>
|
||||
{isDevFeaturesEnabled && <ProtectedAppCard />}
|
||||
{(filterCategories.length > 0 ? filterCategories : allAppGuideCategories).map(
|
||||
(category) =>
|
||||
structuredMetadata[category].length > 0 && (
|
||||
<GuideCardGroup
|
||||
key={category}
|
||||
className={styles.guideGroup}
|
||||
hasCardBorder={hasCardBorder}
|
||||
hasCardButton={hasCardButton}
|
||||
categoryName={t(`categories.${category}`)}
|
||||
guides={structuredMetadata[category]}
|
||||
onClickGuide={onClickGuide}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{selectedGuide?.target !== 'API' && showCreateForm && (
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: _.unit(4);
|
||||
margin-bottom: _.unit(4);
|
||||
|
||||
label {
|
||||
color: var(--color-text-secondary);
|
||||
font: var(--font-section-head-1);
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: _.unit(6) _.unit(8);
|
||||
gap: _.unit(6);
|
||||
background-color: var(--color-layer-1);
|
||||
border-radius: 12px;
|
||||
|
||||
.logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.name {
|
||||
font: var(--font-label-2);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.description {
|
||||
font: var(--font-body-2);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import { Theme } from '@logto/schemas';
|
||||
import { useState } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import ProtectedAppDarkIcon from '@/assets/icons/protected-app-dark.svg';
|
||||
import ProtectedAppIcon from '@/assets/icons/protected-app.svg';
|
||||
import Button from '@/ds-components/Button';
|
||||
import TextLink from '@/ds-components/TextLink';
|
||||
import useDocumentationUrl from '@/hooks/use-documentation-url';
|
||||
import useTheme from '@/hooks/use-theme';
|
||||
|
||||
import ProtectedAppModal from '../ProtectedAppModal';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
function ProtectedAppCard() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console.protected_app' });
|
||||
const { documentationSiteUrl } = useDocumentationUrl();
|
||||
const [showCreateModal, setShowCreateModal] = useState<boolean>(false);
|
||||
const theme = useTheme();
|
||||
const Icon = theme === Theme.Light ? ProtectedAppIcon : ProtectedAppDarkIcon;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.container}>
|
||||
<label>{t('name')}</label>
|
||||
<div className={styles.card}>
|
||||
<Icon className={styles.logo} />
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.name}>{t('title')}</div>
|
||||
<div className={styles.description}>
|
||||
<Trans
|
||||
components={{
|
||||
// TODO: @charles Update documentation URL when it's ready
|
||||
a: <TextLink href={documentationSiteUrl} targetBlank="noopener" />,
|
||||
}}
|
||||
>
|
||||
{t('description')}
|
||||
</Trans>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
title="protected_app.fast_create"
|
||||
onClick={() => {
|
||||
setShowCreateModal(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{showCreateModal && (
|
||||
<ProtectedAppModal
|
||||
onClose={() => {
|
||||
setShowCreateModal(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProtectedAppCard;
|
|
@ -0,0 +1,29 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.fieldWrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.subdomain {
|
||||
flex: 1;
|
||||
|
||||
> div {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.domain {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 _.unit(4);
|
||||
border: 1px solid var(--color-border);
|
||||
height: 36px;
|
||||
border-radius: 0 6px 6px 0;
|
||||
border-left: none;
|
||||
font: var(--font-body-2);
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-specific-unselected-disabled);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
import { useFormContext } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
function ProtectedAppForm() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console.protected_app' });
|
||||
const {
|
||||
register,
|
||||
formState: { errors },
|
||||
} = useFormContext<ProtectedAppForm>();
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormField isRequired title="protected_app.form.domain_field_label">
|
||||
<div className={styles.fieldWrapper}>
|
||||
<TextInput
|
||||
className={styles.subdomain}
|
||||
{...register('subDomain', { required: true })}
|
||||
placeholder={t('form.domain_field_placeholder')}
|
||||
error={Boolean(errors.subDomain)}
|
||||
/>
|
||||
{/** TODO: @charles Hard-coded for now, will update to read from API later. */}
|
||||
<div className={styles.domain}>.protected.app</div>
|
||||
</div>
|
||||
</FormField>
|
||||
<FormField isRequired title="protected_app.form.url_field_label">
|
||||
<TextInput
|
||||
{...register('origin', { required: true })}
|
||||
placeholder={t('form.url_field_placeholder')}
|
||||
error={Boolean(errors.origin)}
|
||||
/>
|
||||
</FormField>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProtectedAppForm;
|
|
@ -0,0 +1,4 @@
|
|||
type ProtectedAppForm = {
|
||||
subDomain: string;
|
||||
origin: string;
|
||||
};
|
|
@ -0,0 +1,82 @@
|
|||
import { ApplicationType, type Application } from '@logto/schemas';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
import Button from '@/ds-components/Button';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import * as modalStyles from '@/scss/modal.module.scss';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
|
||||
import ProtectedAppForm from '../ProtectedAppForm';
|
||||
|
||||
type Props = {
|
||||
onClose?: (createdApp?: Application) => void;
|
||||
};
|
||||
|
||||
function ProtectedAppModal({ onClose }: Props) {
|
||||
const methods = useForm<ProtectedAppForm>();
|
||||
const {
|
||||
handleSubmit,
|
||||
formState: { isSubmitting },
|
||||
} = methods;
|
||||
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const api = useApi();
|
||||
|
||||
const onSubmit = handleSubmit(
|
||||
trySubmitSafe(async (data) => {
|
||||
if (isSubmitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
const createdApp = await api
|
||||
.post('api/applications', {
|
||||
json: {
|
||||
name: data.subDomain,
|
||||
type: ApplicationType.Protected,
|
||||
protectedAppMetadata: data,
|
||||
},
|
||||
})
|
||||
.json<Application>();
|
||||
toast.success(t('applications.application_created'));
|
||||
onClose?.(createdApp);
|
||||
})
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
shouldCloseOnEsc
|
||||
isOpen
|
||||
className={modalStyles.content}
|
||||
overlayClassName={modalStyles.overlay}
|
||||
onRequestClose={() => {
|
||||
onClose?.();
|
||||
}}
|
||||
>
|
||||
<ModalLayout
|
||||
title="protected_app.modal_title"
|
||||
subtitle="protected_app.modal_subtitle"
|
||||
size="large"
|
||||
footer={
|
||||
<Button
|
||||
size="large"
|
||||
type="primary"
|
||||
title="protected_app.form.create_application"
|
||||
isLoading={isSubmitting}
|
||||
onClick={onSubmit}
|
||||
/>
|
||||
}
|
||||
onClose={onClose}
|
||||
>
|
||||
<FormProvider {...methods}>
|
||||
<ProtectedAppForm />
|
||||
</FormProvider>
|
||||
</ModalLayout>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProtectedAppModal;
|
|
@ -9,8 +9,7 @@ export const applicationTypeI18nKey = Object.freeze({
|
|||
[ApplicationType.SPA]: 'applications.type.spa',
|
||||
[ApplicationType.Traditional]: 'applications.type.traditional',
|
||||
[ApplicationType.MachineToMachine]: 'applications.type.machine_to_machine',
|
||||
// TODO @sijie: update with new phrase
|
||||
[ApplicationType.Protected]: 'applications.type.traditional',
|
||||
[ApplicationType.Protected]: 'applications.type.protected',
|
||||
} as const);
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,6 +41,14 @@ const applications = {
|
|||
subtitle: 'Eine Anwendung (normalerweise ein Dienst), die direkt mit Ressourcen kommuniziert',
|
||||
description: 'z.B. Backend Dienst',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -38,6 +38,11 @@ const applications = {
|
|||
subtitle: 'An app (usually a service) that directly talks to resources',
|
||||
description: 'E.g., Backend service',
|
||||
},
|
||||
protected: {
|
||||
title: 'Protected App',
|
||||
subtitle: 'An app that is protected by Logto', // Not in use
|
||||
description: 'N/A', // Not in use
|
||||
},
|
||||
third_party: {
|
||||
title: 'Third-party app',
|
||||
subtitle: 'An app that is used as a third-party IdP connector',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
const protected_app = {
|
||||
name: 'Protected App',
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
fast_create: 'Fast create',
|
||||
modal_title: 'Create protected app',
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
domain_field_label: 'App domain protected',
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
url_field_label: 'Origin URL',
|
||||
url_field_placeholder: 'https://',
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
domain_required: 'Subdomain is required',
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
url_required: 'Origin URL is required.',
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -41,6 +41,14 @@ const applications = {
|
|||
subtitle: 'Una aplicación (generalmente un servicio) que habla directamente con recursos',
|
||||
description: 'Por ejemplo, servicio backend',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -42,6 +42,14 @@ const applications = {
|
|||
'Une application (généralement un service) qui communique directement avec les ressources',
|
||||
description: 'Par exemple, un service backend',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -41,6 +41,14 @@ const applications = {
|
|||
subtitle: "Un'app (solitamente un servizio) che comunica direttamente con le risorse",
|
||||
description: 'E.g., servizio backend',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -40,6 +40,14 @@ const applications = {
|
|||
subtitle: 'リソースに直接アクセスするアプリケーション(通常はサービス)',
|
||||
description: '例:バックエンドサービス',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -40,6 +40,14 @@ const applications = {
|
|||
subtitle: '직접 리소스에 접근하는 엡(서비스)',
|
||||
description: '예) 백엔드 서비스',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -41,6 +41,14 @@ const applications = {
|
|||
subtitle: 'Aplikacja (zazwyczaj usługa), która bezpośrednio komunikuje się z zasobami',
|
||||
description: 'Na przykład usługa backendowa',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -41,6 +41,14 @@ const applications = {
|
|||
subtitle: 'Um aplicativo (geralmente um serviço) que fala diretamente com os recursos',
|
||||
description: 'Ex: serviço de backend',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -40,6 +40,14 @@ const applications = {
|
|||
subtitle: 'Uma aplicação (normalmente um serviço) que se comunica diretamente com recursos',
|
||||
description: 'Ex., serviço back-end',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -40,6 +40,14 @@ const applications = {
|
|||
subtitle: 'Приложение (обычно сервис), которое напрямую общается с ресурсами',
|
||||
description: 'Например, backend-сервис',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -41,6 +41,14 @@ const applications = {
|
|||
subtitle: 'Kaynaklarla doğrudan iletişim kuran bir uygulama (genellikle bir servis)',
|
||||
description: 'Örneğin, Backend servisi',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -39,6 +39,14 @@ const applications = {
|
|||
subtitle: '直接与资源对话的应用程序(通常是服务)',
|
||||
description: '例如,后端服务',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -39,6 +39,14 @@ const applications = {
|
|||
subtitle: '直接與資源對話的應用程序(通常是服務)',
|
||||
description: '例如,後端服務',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -39,6 +39,14 @@ const applications = {
|
|||
subtitle: '直接與資源對話的應用程序(通常是服務)',
|
||||
description: '例如,後端服務',
|
||||
},
|
||||
protected: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
subtitle: 'An app that is protected by Logto',
|
||||
/** UNTRANSLATED */
|
||||
description: 'N/A',
|
||||
},
|
||||
third_party: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Third-party app',
|
||||
|
|
|
@ -23,6 +23,7 @@ import organization_details from './organization-details.js';
|
|||
import organizations from './organizations.js';
|
||||
import permissions from './permissions.js';
|
||||
import profile from './profile.js';
|
||||
import protected_app from './protected-app.js';
|
||||
import role_details from './role-details.js';
|
||||
import roles from './roles.js';
|
||||
import session_expired from './session-expired.js';
|
||||
|
@ -83,6 +84,7 @@ const admin_console = {
|
|||
mfa,
|
||||
organizations,
|
||||
organization_details,
|
||||
protected_app,
|
||||
};
|
||||
|
||||
export default Object.freeze(admin_console);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const protected_app = {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Protected App',
|
||||
/** UNTRANSLATED */
|
||||
title: 'Create a Protected App with epic speed and simplicity',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Deploy with Logto secure workers, powered by Cloudflare's edge network for top-tier performance and 0ms cold starts worldwide. <a>Learn more</a>",
|
||||
/** UNTRANSLATED */
|
||||
fast_create: 'Fast create',
|
||||
/** UNTRANSLATED */
|
||||
modal_title: 'Create protected app',
|
||||
/** UNTRANSLATED */
|
||||
modal_subtitle: 'No more integrating Logto SDK. Create you web app easily.',
|
||||
form: {
|
||||
/** UNTRANSLATED */
|
||||
domain_field_label: 'App domain protected',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_placeholder: 'Custom subdomain',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_description:
|
||||
'Specify the app domain that will be protected by authentication and redirected to the Origin URL.',
|
||||
/** UNTRANSLATED */
|
||||
domain_field_tooltip:
|
||||
"You can use a 'protected.app' subdomain powered by Logto for quick testing or online access, which remains consistently valid. After creation, your custom domain name can be added.",
|
||||
/** UNTRANSLATED */
|
||||
url_field_label: 'Origin URL',
|
||||
/** UNTRANSLATED */
|
||||
url_field_placeholder: 'https://',
|
||||
/** UNTRANSLATED */
|
||||
url_field_tooltip:
|
||||
"Enter primary website address of your application, excluding any '/routes'. After creation, you can customize route authentication rules.\n\nNote: The Origin URL itself won't require authentication; only accesses via the added app domain will be protected.",
|
||||
/** UNTRANSLATED */
|
||||
create_application: 'Create application',
|
||||
errors: {
|
||||
/** UNTRANSLATED */
|
||||
domain_required: 'Subdomain is required',
|
||||
/** UNTRANSLATED */
|
||||
domain_in_use: 'This subdomain name is already in use.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_domain_format:
|
||||
"Invalid subdomain format: use only lowercase letters, hyphens '-', and underscores '_'.",
|
||||
/** UNTRANSLATED */
|
||||
url_required: 'Origin URL is required.',
|
||||
/** UNTRANSLATED */
|
||||
invalid_url:
|
||||
"Invalid Origin URL format: Use http:// or https://. Note: '/routes' is not currently supported.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(protected_app);
|
|
@ -160,6 +160,7 @@
|
|||
--color-env-tag-production: rgba(131, 218, 133, 35%);
|
||||
--color-specific-icon-bg: #f3effa;
|
||||
--color-specific-toggle-off-enable: var(--color-neutral-90);
|
||||
--color-specific-unselected-disabled: var(--color-hover); // 8% Neutral-10
|
||||
|
||||
// Shadows
|
||||
--shadow-1: 0 4px 8px rgba(0, 0, 0, 8%);
|
||||
|
@ -362,6 +363,7 @@
|
|||
--color-env-tag-production: rgba(104, 190, 108, 36%);
|
||||
--color-specific-icon-bg: rgba(247, 248, 248, 12%);
|
||||
--color-specific-toggle-off-enable: var(--color-neutral-90);
|
||||
--color-specific-unselected-disabled: var(--color-hover); // 8% Neutral-10
|
||||
|
||||
// Shadows
|
||||
--shadow-1: 0 4px 8px rgba(0, 0, 0, 8%);
|
||||
|
|
Loading…
Add table
Reference in a new issue