diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b7baaeb..15c4605 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,10 +14,6 @@ on: - minor - major -permissions: - contents: write - pull-requests: write - jobs: release-please: runs-on: ubuntu-latest @@ -36,13 +32,17 @@ jobs: with: node-version: '20' - - name: 🚀 Create Manual Release PR + - name: 🚀 Create Manual Release Commit if: github.event_name == 'workflow_dispatch' id: manual_release run: | npm install -g release-please npm install semver + # Configure git + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + # Get current version from manifest CURRENT_VERSION=$(cat .release-please-manifest.json | jq -r '.Website') echo "Current version: $CURRENT_VERSION" @@ -57,19 +57,46 @@ jobs: echo "Next version will be: $NEXT_VERSION" - # Create release PR with specific version - release-please release-pr \ - --repo-url="https://github.com/${{ github.repository }}" \ - --config-file=release-please-config.json \ - --manifest-file=.release-please-manifest.json \ - --release-as=$NEXT_VERSION \ - --skip-labeling \ - --token=${{ secrets.GITHUB_TOKEN }} - + # Update version in package.json + cd Website + npm version $NEXT_VERSION --no-git-tag-version + cd .. + + # Update manifest file + jq --arg version "$NEXT_VERSION" '.Website = $version' .release-please-manifest.json > temp.json && mv temp.json .release-please-manifest.json + + # Generate changelog entry + echo "## [$NEXT_VERSION] - $(date +'%Y-%m-%d')" > temp_changelog.md + echo "" >> temp_changelog.md + echo "### Changed" >> temp_changelog.md + echo "- Manual ${{ github.event.inputs.release_type }} release" >> temp_changelog.md + echo "" >> temp_changelog.md + + # Prepend to existing changelog if it exists + if [ -f "Website/CHANGELOG.md" ]; then + cat temp_changelog.md Website/CHANGELOG.md > temp_full_changelog.md + mv temp_full_changelog.md Website/CHANGELOG.md + else + mv temp_changelog.md Website/CHANGELOG.md + fi + + # Commit and push changes + git add . + git commit -m "chore(release): release $NEXT_VERSION + + Release type: ${{ github.event.inputs.release_type }} + Previous version: $CURRENT_VERSION + New version: $NEXT_VERSION" + + git push origin HEAD + echo "releases_created=true" >> $GITHUB_OUTPUT + echo "version=$NEXT_VERSION" >> $GITHUB_OUTPUT - name: 📝 Manual Release Summary if: github.event_name == 'workflow_dispatch' run: | - echo "✅ Manual release PR created with type: ${{ github.event.inputs.release_type }}" - echo "🔍 Check the Pull Requests tab for the release PR to review and merge." + echo "✅ Manual release commit created with type: ${{ github.event.inputs.release_type }}" + echo "🏷️ New version: ${{ steps.manual_release.outputs.version }}" + echo "📝 Changes have been committed and pushed to the current branch." + echo "🔗 View the commit: https://github.com/${{ github.repository }}/commit/$(git rev-parse HEAD)" diff --git a/Generator/MetadataExtensions.cs b/Generator/MetadataExtensions.cs index 03ec00a..3577e4d 100644 --- a/Generator/MetadataExtensions.cs +++ b/Generator/MetadataExtensions.cs @@ -58,11 +58,13 @@ private static bool StandardDescriptionHasChanged(this IEnumerable<(string Logic return EnglishDefaultFields.Concat(new[] { ("statuscode", "Status Reason", $"Reason for the status of the {entityDisplayName}"), ("statecode", "Status Reason", $"Status of the {entityDisplayName}"), + ("organizationid", "Organization", $"Unique identifier of the organization associated with the {entityDisplayName}."), }); default: return EnglishDefaultFields.Concat(new[] { ("statuscode", "Status Reason", $"Reason for the status of the {entityDisplayName}"), ("statecode", "Status Reason", $"Status of the {entityDisplayName}"), + ("organizationid", "Organization", $"Unique identifier of the organization associated with the {entityDisplayName}."), }); ; } } @@ -225,6 +227,7 @@ private static bool StandardDescriptionHasChanged(this IEnumerable<(string Logic ( "utcconversiontimezonecode", "Tidszonekode til UTC-konvertering", "Den tidszonekode, der var i brug ved oprettelse af posten." ), ( "utcconversiontimezonecode", "Tidszonekode for UTC-konvertering", "Den tidszonekode, der var i brug ved oprettelse af posten." ), ( "versionnumber", "Versionsnummer", "Versionsnummer" ), - ( "versionnumber", "Versionsnummer", "Versionsnummer for aktiviteten." ) + ( "versionnumber", "Versionsnummer", "Versionsnummer for aktiviteten." ), + ( "organizationid", "Organisations-id", "Entydigt id for organisationen" ), }; } diff --git a/Website/components/attributes/BooleanAttribute.tsx b/Website/components/attributes/BooleanAttribute.tsx index 43cace7..6570bb1 100644 --- a/Website/components/attributes/BooleanAttribute.tsx +++ b/Website/components/attributes/BooleanAttribute.tsx @@ -1,45 +1,49 @@ +import { useIsMobile } from "@/hooks/use-mobile"; import { BooleanAttributeType } from "@/lib/Types" import { CheckCircle, Circle } from "lucide-react" export default function BooleanAttribute({ attribute }: { attribute: BooleanAttributeType }) { + + const isMobile = useIsMobile(); + return (
- Boolean - {attribute.DefaultValue !== null && ( - - + Boolean + {attribute.DefaultValue !== null && !isMobile && ( + + Default: {attribute.DefaultValue === true ? attribute.TrueLabel : attribute.FalseLabel} )}
-
+
{attribute.DefaultValue === true ? ( - + ) : ( - + )} - {attribute.TrueLabel} + {attribute.TrueLabel}
- + True
-
+
{attribute.DefaultValue === false ? ( - + ) : ( - + )} - {attribute.FalseLabel} + {attribute.FalseLabel}
- + False
diff --git a/Website/components/attributes/ChoiceAttribute.tsx b/Website/components/attributes/ChoiceAttribute.tsx index 59717db..aa087fb 100644 --- a/Website/components/attributes/ChoiceAttribute.tsx +++ b/Website/components/attributes/ChoiceAttribute.tsx @@ -1,15 +1,19 @@ +import { useIsMobile } from "@/hooks/use-mobile" import { ChoiceAttributeType } from "@/lib/Types" import { formatNumberSeperator } from "@/lib/utils" -import { CheckCircle, Circle } from "lucide-react" +import { CheckCircle, Circle, Square, CheckSquare } from "lucide-react" export default function ChoiceAttribute({ attribute }: { attribute: ChoiceAttributeType }) { + + const isMobile = useIsMobile(); + return (
- {attribute.Type}-select - {attribute.DefaultValue !== null && attribute.DefaultValue !== -1 && ( - - + {attribute.Type}-select + {attribute.DefaultValue !== null && attribute.DefaultValue !== -1 && !isMobile && ( + + Default: {attribute.Options.find(o => o.Value === attribute.DefaultValue)?.Name} )} @@ -17,32 +21,42 @@ export default function ChoiceAttribute({ attribute }: { attribute: ChoiceAttrib
{attribute.Options.map(option => (
-
+
- {option.Value === attribute.DefaultValue ? ( - + {attribute.Type === "Multi" ? ( + // For multi-select, show checkboxes + option.Value === attribute.DefaultValue ? ( + + ) : ( + + ) ) : ( - + // For single-select, show radio buttons + option.Value === attribute.DefaultValue ? ( + + ) : ( + + ) )} - {option.Name} + {option.Name}
{option.Color && (
)}
- + {formatNumberSeperator(option.Value)}
{option.Description && ( -
+
{option.Description}
)} diff --git a/Website/components/attributes/DateTimeAttribute.tsx b/Website/components/attributes/DateTimeAttribute.tsx index b5655a2..6d6b69c 100644 --- a/Website/components/attributes/DateTimeAttribute.tsx +++ b/Website/components/attributes/DateTimeAttribute.tsx @@ -1,5 +1,5 @@ import { DateTimeAttributeType } from "@/lib/Types"; export default function DateTimeAttribute({ attribute } : { attribute: DateTimeAttributeType }) { - return <>{attribute.Format} - {attribute.Behavior} + return <>{attribute.Format} - {attribute.Behavior} } \ No newline at end of file diff --git a/Website/components/attributes/DecimalAttribute.tsx b/Website/components/attributes/DecimalAttribute.tsx index 2a9be40..cd73150 100644 --- a/Website/components/attributes/DecimalAttribute.tsx +++ b/Website/components/attributes/DecimalAttribute.tsx @@ -8,8 +8,8 @@ export default function MoneyAttribute({ attribute }: { attribute: DecimalAttrib : FormatDecimal return <> -

{attribute.Type} ({formatNumber(attribute.MinValue)} to {formatNumber(attribute.MaxValue)})

-

Precision: {attribute.Precision}

+

{attribute.Type} ({formatNumber(attribute.MinValue)} to {formatNumber(attribute.MaxValue)})

+

Precision: {attribute.Precision}

} diff --git a/Website/components/attributes/FileAttribute.tsx b/Website/components/attributes/FileAttribute.tsx index 2afee50..39ba278 100644 --- a/Website/components/attributes/FileAttribute.tsx +++ b/Website/components/attributes/FileAttribute.tsx @@ -2,5 +2,5 @@ import { FileAttributeType } from "@/lib/Types"; import { formatNumberSeperator } from "@/lib/utils"; export default function FileAttribute({ attribute } : { attribute: FileAttributeType }) { - return <>File (Max {formatNumberSeperator(attribute.MaxSize)}KB) + return <>File (Max {formatNumberSeperator(attribute.MaxSize)}KB) } \ No newline at end of file diff --git a/Website/components/attributes/GenericAttribute.tsx b/Website/components/attributes/GenericAttribute.tsx index b94090e..d0e0db1 100644 --- a/Website/components/attributes/GenericAttribute.tsx +++ b/Website/components/attributes/GenericAttribute.tsx @@ -1,5 +1,5 @@ import { GenericAttributeType } from "@/lib/Types"; export default function GenericAttribute({ attribute } : { attribute: GenericAttributeType }) { - return {attribute.Type} + return {attribute.Type} } \ No newline at end of file diff --git a/Website/components/attributes/IntegerAttribute.tsx b/Website/components/attributes/IntegerAttribute.tsx index a5a8ea5..8c72f40 100644 --- a/Website/components/attributes/IntegerAttribute.tsx +++ b/Website/components/attributes/IntegerAttribute.tsx @@ -2,7 +2,7 @@ import { IntegerAttributeType } from "@/lib/Types" import { formatNumberSeperator } from "@/lib/utils" export default function IntegerAttribute({ attribute } : { attribute: IntegerAttributeType }) { - return <>{attribute.Format} ({FormatNumber(attribute.MinValue)} to {FormatNumber(attribute.MaxValue)}) + return <>{attribute.Format} ({FormatNumber(attribute.MinValue)} to {FormatNumber(attribute.MaxValue)}) } function FormatNumber(number: number) { diff --git a/Website/components/attributes/LookupAttribute.tsx b/Website/components/attributes/LookupAttribute.tsx index 54d53c4..4ac5f5d 100644 --- a/Website/components/attributes/LookupAttribute.tsx +++ b/Website/components/attributes/LookupAttribute.tsx @@ -6,26 +6,26 @@ export default function LookupAttribute({ attribute }: { attribute: LookupAttrib const { scrollToSection } = useDatamodelView(); - return <> -

Lookup

-
+ return
+

Lookup

+
{attribute.Targets .map(target => target.IsInSolution ? :
- - {target.Name} + + {target.Name}
)}
- +
} \ No newline at end of file diff --git a/Website/components/attributes/StatusAttribute.tsx b/Website/components/attributes/StatusAttribute.tsx index 889a5a0..41974bb 100644 --- a/Website/components/attributes/StatusAttribute.tsx +++ b/Website/components/attributes/StatusAttribute.tsx @@ -11,16 +11,16 @@ export default function StatusAttribute({ attribute }: { attribute: StatusAttrib }, {} as Record) return ( -
- State/Status +
+ State/Status {Object.entries(groupedOptions).map(([state, options]) => (
- {state} -
+ {state} +
{options.map(option => (
- {option.Name} - {formatNumberSeperator(option.Value)} + {option.Name} + {formatNumberSeperator(option.Value)}
))}
diff --git a/Website/components/attributes/StringAttribute.tsx b/Website/components/attributes/StringAttribute.tsx index a25b74b..2c2e461 100644 --- a/Website/components/attributes/StringAttribute.tsx +++ b/Website/components/attributes/StringAttribute.tsx @@ -4,5 +4,5 @@ import { StringAttributeType } from "@/lib/Types"; import { formatNumberSeperator } from "@/lib/utils"; export default function StringAttribute({ attribute } : { attribute: StringAttributeType }) { - return <>Text ({formatNumberSeperator(attribute.MaxLength)}){attribute.Format !== "Text" ? ` - ${attribute.Format}` : ""}; + return <>Text ({formatNumberSeperator(attribute.MaxLength)}){attribute.Format !== "Text" ? ` - ${attribute.Format}` : ""}; } \ No newline at end of file diff --git a/Website/components/datamodelview/Attributes.tsx b/Website/components/datamodelview/Attributes.tsx index e489037..6e18c35 100644 --- a/Website/components/datamodelview/Attributes.tsx +++ b/Website/components/datamodelview/Attributes.tsx @@ -125,23 +125,23 @@ export const Attributes = ({ entity }: IAttributeProps) => { ] return <> -
+
- + setSearchQuery(e.target.value)} - className="pl-8" + className="pl-6 h-8 text-xs md:pl-8 md:h-10 md:text-sm" />
setSearchQuery(e.target.value)} - className="pl-8" + className="pl-6 h-8 text-xs md:pl-8 md:h-10 md:text-sm" />
{searchQuery && ( @@ -98,10 +98,10 @@ function Keys({ entity }: { entity: EntityType }) { variant="ghost" size="icon" onClick={() => setSearchQuery("")} - className="h-10 w-10 text-gray-500 hover:text-gray-700" + className="h-8 w-8 text-gray-500 hover:text-gray-700 md:h-10 md:w-10" title="Clear search" > - + )}
@@ -128,7 +128,7 @@ function Keys({ entity }: { entity: EntityType }) { handleSort('name')} >
@@ -137,7 +137,7 @@ function Keys({ entity }: { entity: EntityType }) {
handleSort('logicalName')} >
@@ -146,7 +146,7 @@ function Keys({ entity }: { entity: EntityType }) {
handleSort('attributes')} >
@@ -164,14 +164,14 @@ function Keys({ entity }: { entity: EntityType }) { index % 2 === 0 ? 'bg-white' : 'bg-gray-50/50' }`} > - {key.Name} - {key.LogicalName} - + {key.Name} + {key.LogicalName} +
{key.KeyAttributes.map((attr, i) => ( {attr} diff --git a/Website/components/datamodelview/Relationships.tsx b/Website/components/datamodelview/Relationships.tsx index 499c1c0..8b48d73 100644 --- a/Website/components/datamodelview/Relationships.tsx +++ b/Website/components/datamodelview/Relationships.tsx @@ -115,23 +115,23 @@ export const Relationships = ({ entity }: IRelationshipsProps) => { ] return <> -
+
- + setSearchQuery(e.target.value)} - className="pl-8" + className="pl-6 h-8 text-xs md:pl-8 md:h-10 md:text-sm" />
handleSearch(e.target.value)} + className="pl-8 pr-8 h-8 text-xs" + /> + {searchTerm && ( + + )} +
+
+ +
{ Groups.map((group) =>