Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions pr-all-unpushed-branches.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
# first, create a list of all local branches
LOCAL_BRANCHES=$(git for-each-ref --format='%(refname:short)' refs/heads/)

# remove all branches that have a remote tracking branch
LOCAL_BRANCHES=$(echo "$LOCAL_BRANCHES" | while read BRANCH; do
if [ -z "$(git for-each-ref --format='%(upstream:short)' refs/heads/$BRANCH)" ]; then
echo "$BRANCH"
fi
done)

# then, remove branches that have been pushed to the remote
# shellcheck disable=SC2001
LOCAL_BRANCHES_FORMATTED=$(echo "$LOCAL_BRANCHES" | sed 's|^|refs/heads/|')

REMOTE_BRANCHES=$(git ls-remote origin --heads "$LOCAL_BRANCHES_FORMATTED" | awk '{print $2}' | sed 's|refs/heads/||')
for BRANCH in $REMOTE_BRANCHES; do
LOCAL_BRANCHES=$(echo "$LOCAL_BRANCHES" | grep -v "^$BRANCH$")
done

# now, LOCAL_BRANCHES contains only branches that have not been pushed to the remote
# for each of these branches, create a pull request using the GitHub CLI
for BRANCH in $LOCAL_BRANCHES; do
# echo "Creating pull request for branch: $BRANCH"
# push the branch to the remote
if ! git push -u origin "$BRANCH"; then
echo "Failed to push branch: $BRANCH"
continue
fi

PR_EXISTS=$(gh pr list --head "$BRANCH" --json number --jq '.[].number')
if [ -z "$PR_EXISTS" ]; then
echo "Creating pull request for branch: $BRANCH"
if ! gh pr create -B develop -d -H "$BRANCH" -f -a "@me"; then
echo "Failed to create pull request for branch: $BRANCH"
continue
else
echo "Pull request created for branch: $BRANCH"
fi
else
echo "Pull request already exists for branch: $BRANCH (PR #$PR_EXISTS)"
fi
done
1 change: 1 addition & 0 deletions src/components/modals/ChangeBooleanValueModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const ChangeBooleanValueModal: FC<ChangeBooleanValueModalProps> = ({
const [wasModified, setWasModified] = useState<boolean>(false);

const handleSave = () => {
setWasModified(false);
onSave?.(value);
onClose?.();
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/modals/ChangeEnumValueModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const ChangeEnumValueModal: FC<ChangeEnumValueModalProps> = ({
const [wasModified, setWasModified] = useState<boolean>(false);

const handleSave = () => {
setWasModified(false);
onSave?.(value);
onClose?.();
};
Expand Down Expand Up @@ -98,7 +99,6 @@ const ChangeEnumValueModal: FC<ChangeEnumValueModalProps> = ({
<RadioButton.Group onValueChange={setValue} value={value}>
{possibleValues.map(({ label, value }) => (
<RadioButton.Item
key={value}
value={value}
label={label}
labelVariant="bodyMedium"
Expand Down
1 change: 1 addition & 0 deletions src/components/modals/ChangeTextValueModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const ChangeTextValueModal: FC<NewChangeTextValueModalProps> = ({
return;
}

setWasModified(false);
onSave?.(value);
onClose?.();
};
Expand Down
63 changes: 63 additions & 0 deletions src/components/modals/ConfirmUnsavedDataModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { FC } from 'react';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Box } from 'react-native-flex-layout';
import type { ModalProps } from 'react-native-paper';
import { Button, Portal, Text, useTheme } from 'react-native-paper';

import BaseModal from '@/components/BaseModal';

export type ConfirmUnsavedDataModalInput = false | (() => void);

export interface ConfirmUnsavedDataModalProps
extends Omit<ModalProps, 'children' | 'visible'> {
visible: ConfirmUnsavedDataModalInput;
}

const ConfirmUnsavedDataModal: FC<ConfirmUnsavedDataModalProps> = props => {
const { onDismiss, visible } = props;
const { t } = useTranslation();
const theme = useTheme();

const handleAbort = useCallback(() => {
onDismiss?.();
}, [onDismiss]);

return (
<Portal>
<BaseModal {...props} visible={!!visible}>
<Box p={16}>
<Box mb={8}>
<Text variant="bodyLarge">{t('unsavedDataTips')}</Text>
</Box>
</Box>
<Box
style={{
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
padding: 8,
}}
>
<Button mode="text" onPress={handleAbort} style={{ marginRight: 8 }}>
{t('cancel')}
</Button>
<Button
onPress={() => {
if (typeof visible === 'function') {
visible();
}
onDismiss?.();
}}
mode="contained"
buttonColor={theme.colors.primary}
>
{t('confirm')}
</Button>
</Box>
</BaseModal>
</Portal>
);
};

export default ConfirmUnsavedDataModal;
3 changes: 2 additions & 1 deletion src/components/styled/SettingsSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { Surface, useTheme } from 'react-native-paper';

import styled from 'styled-components';

const settingsSurfaceBorderRadiusFactor = 3;
const settingsSurfaceBorderRadiusFactor = 8;

export const settingsSurfaceRoundness = (theme: ThemeBase) => {
return theme.roundness! * settingsSurfaceBorderRadiusFactor;
};

const InternalSettingsSurface = styled(Surface)`
margin: 4px 16px 12px;
padding: 0 4px;
border-radius: ${props =>
(props.theme.roundness ?? 0) * settingsSurfaceBorderRadiusFactor}px;
`;
Expand Down
2 changes: 1 addition & 1 deletion src/translations
59 changes: 46 additions & 13 deletions src/views/navigation/screens/SettingsGroup/DtuSettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { NRFPaLevel } from '@/types/opendtu/settings';

import ChangeEnumValueModal from '@/components/modals/ChangeEnumValueModal';
import ChangeTextValueModal from '@/components/modals/ChangeTextValueModal';
import type { ConfirmUnsavedDataModalInput } from '@/components/modals/ConfirmUnsavedDataModal';
import ConfirmUnsavedDataModal from '@/components/modals/ConfirmUnsavedDataModal';
import SettingsSurface from '@/components/styled/SettingsSurface';

import useDtuSettings from '@/hooks/useDtuSettings';
Expand Down Expand Up @@ -66,11 +68,28 @@ const DtuSettingsScreen: FC<PropsWithNavigation> = ({ navigation }) => {
const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
const [isSaving, setIsSaving] = useState<boolean>(false);

const handleGetDtuSettings = useCallback(async () => {
setIsRefreshing(true);
await openDtuApi.getDtuConfig();
setIsRefreshing(false);
}, [openDtuApi]);
const hasChanges = useMemo(() => {
return !deepEqual(initialDtuSettings, dtuSettings);
}, [initialDtuSettings, dtuSettings]);

const [confirmRefreshDataModalOpen, setConfirmRefreshDataModalOpen] =
useState<ConfirmUnsavedDataModalInput>(false);

const performRefresh = useCallback(
async (forceRefresh: boolean = false) => {
if (hasChanges && !forceRefresh) {
setConfirmRefreshDataModalOpen(() => () => {
performRefresh(true);
});
return;
}

setIsRefreshing(true);
await openDtuApi.getDtuConfig();
setIsRefreshing(false);
},
[hasChanges, openDtuApi],
);

const handleSave = useCallback(async () => {
if (!dtuSettings) {
Expand All @@ -95,13 +114,11 @@ const DtuSettingsScreen: FC<PropsWithNavigation> = ({ navigation }) => {

useEffect(() => {
if (navigation.isFocused()) {
handleGetDtuSettings();
performRefresh();
}
}, [handleGetDtuSettings, navigation]);

const hasChanges = useMemo(() => {
return !deepEqual(initialDtuSettings, dtuSettings);
}, [initialDtuSettings, dtuSettings]);
// we do not want to include performRefresh here
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [navigation]);
Comment thread Fixed

const [changeSerialModalOpen, setChangeSerialModalOpen] = useState(false);
const [changePollIntervalModalOpen, setChangePollIntervalModalOpen] =
Expand Down Expand Up @@ -148,7 +165,17 @@ const DtuSettingsScreen: FC<PropsWithNavigation> = ({ navigation }) => {
return (
<>
<Appbar.Header>
<Appbar.BackAction onPress={() => navigation.goBack()} />
<Appbar.BackAction
onPress={() => {
if (hasChanges) {
setConfirmRefreshDataModalOpen(() => () => {
navigation.goBack();
});
return;
}
navigation.goBack();
}}
/>
<Appbar.Content title={t('settings.dtuSettings.title')} />
{isSaving || hasChanges ? (
<Appbar.Action
Expand All @@ -165,7 +192,7 @@ const DtuSettingsScreen: FC<PropsWithNavigation> = ({ navigation }) => {
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={handleGetDtuSettings}
onRefresh={performRefresh}
colors={[theme.colors.primary]}
progressBackgroundColor={theme.colors.elevation.level3}
tintColor={theme.colors.primary}
Expand Down Expand Up @@ -501,6 +528,12 @@ const DtuSettingsScreen: FC<PropsWithNavigation> = ({ navigation }) => {
return true;
}}
/>
<ConfirmUnsavedDataModal
visible={confirmRefreshDataModalOpen}
onDismiss={() => {
setConfirmRefreshDataModalOpen(false);
}}
/>
</>
);
};
Expand Down
Loading