{}}
+ visitedSteps={completedSteps}
validationResults={{
connection: { valid: true },
repository: { valid: true },
migrate: { valid: true },
}}
- getNextUrl={() => ''}
/>
{activeStep === 'connection' && }
- {activeStep === 'repository' && }
- {activeStep === 'migrate' && }
+ {activeStep === 'repository' && }
+ {activeStep === 'migrate' && }
@@ -140,7 +147,11 @@ export function ProvisioningWizard() {
)}
);
}
@@ -116,14 +145,19 @@ export function RepositoryStep() {
if (type === 'local') {
return (
);
}
diff --git a/public/app/features/provisioning/Wizard/RequestErrorAlert.tsx b/public/app/features/provisioning/Wizard/RequestErrorAlert.tsx
new file mode 100644
index 00000000000..6ea195e1821
--- /dev/null
+++ b/public/app/features/provisioning/Wizard/RequestErrorAlert.tsx
@@ -0,0 +1,36 @@
+import { Alert } from '@grafana/ui';
+import { getMessageFromError } from 'app/core/utils/errors';
+
+interface RequestErrorAlertProps {
+ request: {
+ isError: boolean;
+ error?: unknown;
+ endpointName?: string;
+ };
+ title?: string;
+}
+
+function getDefaultTitle(endpointName?: string): string {
+ switch (endpointName) {
+ case 'createRepositoryMigrate':
+ return 'Failed to migrate dashboards';
+ case 'createOrUpdateRepository':
+ return 'Failed to save repository settings';
+ default:
+ return 'Operation failed';
+ }
+}
+
+export function RequestErrorAlert({ request, title }: RequestErrorAlertProps) {
+ if (!request.isError) {
+ return null;
+ }
+
+ const errorTitle = title || getDefaultTitle(request.endpointName);
+
+ return (
+
+ {getMessageFromError(request.error)}
+
+ );
+}
diff --git a/public/app/features/provisioning/Wizard/Stepper.tsx b/public/app/features/provisioning/Wizard/Stepper.tsx
index a5725fe2d86..1ee061f5579 100644
--- a/public/app/features/provisioning/Wizard/Stepper.tsx
+++ b/public/app/features/provisioning/Wizard/Stepper.tsx
@@ -1,5 +1,4 @@
import { css, cx } from '@emotion/css';
-import { MouseEvent } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, Icon } from '@grafana/ui';
@@ -13,19 +12,15 @@ export interface Step {
export interface Props {
activeStep?: T;
- onStepChange: (step: T, event: MouseEvent) => void;
reportId?: string;
visitedSteps?: T[];
steps: Array>;
validationResults: Record;
- getNextUrl: (step: T) => string;
}
export function Stepper({
validationResults,
- onStepChange,
visitedSteps = [],
- getNextUrl,
steps,
activeStep = steps[0]?.id,
}: Props) {
@@ -37,9 +32,9 @@ export function Stepper({
{steps.map((step) => {
const isLast = step.id === lastStep.id;
const isActive = step.id === activeStep;
- const isVisited = visitedSteps.includes(step.id) || activeStep === lastStep.id;
- const hasMissingFields = !isLast && !validationResults[step.id].valid;
- const showIndicator = !isActive && !isLast && isVisited;
+ const isVisited = visitedSteps.includes(step.id);
+ const hasMissingFields = !validationResults[step.id].valid;
+ const showIndicator = !isActive && isVisited;
const successField = showIndicator && !hasMissingFields;
const warnField = showIndicator && hasMissingFields;
const itemStyles = cx(styles.item, {
diff --git a/public/app/features/provisioning/utils/git.ts b/public/app/features/provisioning/utils/git.ts
index 1e89f106a5e..a0a04b69ec2 100644
--- a/public/app/features/provisioning/utils/git.ts
+++ b/public/app/features/provisioning/utils/git.ts
@@ -1,4 +1,4 @@
-import { RepositorySpec } from '../api';
+import { Repository, RepositorySpec } from '../api';
export function createPRLink(spec?: RepositorySpec, dashboardName?: string, ref?: string, comment?: string) {
if (!spec || spec.type !== 'github' || !ref) {
@@ -21,3 +21,15 @@ export function validateBranchName(branchName?: string) {
return branchName && branchNameRegex.test(branchName!);
}
+
+export function getRemoteURL(repo: Repository) {
+ if (repo.spec?.type === 'github') {
+ const spec = repo.spec.github;
+ let url = spec?.url || '';
+ if (spec?.branch) {
+ url += `/tree/${spec.branch}`;
+ }
+ return url;
+ }
+ return undefined;
+}