mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-28 17:23:28 +00:00
Micro interaction for manage tab (#139)
This commit is contained in:
parent
ddb1bc3f94
commit
d9392c8ffd
@ -20,12 +20,32 @@
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid rgba(0, 0, 0, 0.1);
|
||||
border-left-color: rgba(37, 99, 235, 1);
|
||||
border-left-color: #7147e8;
|
||||
background: transparent;
|
||||
animation: rotate 1s linear infinite;
|
||||
margin: 6rem auto;
|
||||
}
|
||||
|
||||
.loader.loader-sm {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-width: 2px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.loader.loader-success {
|
||||
border-left-color: #51c41a;
|
||||
}
|
||||
|
||||
.loader.loader-error {
|
||||
border-left-color: #ff4c3b;
|
||||
}
|
||||
|
||||
.loader.loader-white {
|
||||
border-color: #ffffff;
|
||||
border-right-color: transparent;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0);
|
||||
|
||||
@ -15,10 +15,46 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import './Loader.css';
|
||||
const Loader: Function = (): JSX.Element => {
|
||||
return <div className="loader" />;
|
||||
|
||||
type Props = {
|
||||
size?: 'default' | 'small';
|
||||
type?: 'default' | 'success' | 'error' | 'white';
|
||||
};
|
||||
|
||||
const Loader: FunctionComponent<Props> = ({
|
||||
size = 'default',
|
||||
type = 'default',
|
||||
}: Props): JSX.Element => {
|
||||
let classes = 'loader';
|
||||
switch (size) {
|
||||
case 'small':
|
||||
classes += ' loader-sm';
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'success':
|
||||
classes += ' loader-success';
|
||||
|
||||
break;
|
||||
case 'error':
|
||||
classes += ' loader-error';
|
||||
|
||||
break;
|
||||
case 'white':
|
||||
classes += ' loader-white';
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return <div className={classes} />;
|
||||
};
|
||||
|
||||
export default Loader;
|
||||
|
||||
@ -24,11 +24,15 @@ import SVGIcons from '../../utils/SvgUtils';
|
||||
import { Button } from '../buttons/Button/Button';
|
||||
import CardListItem from '../card-list/CardListItem/CardWithListItems';
|
||||
import DropDownList from '../dropdown/DropDownList';
|
||||
import Loader from '../Loader/Loader';
|
||||
|
||||
type Props = {
|
||||
currentTier?: string;
|
||||
currentUser?: string;
|
||||
onSave: (owner: TableDetail['owner'], tier: TableDetail['tier']) => void;
|
||||
onSave: (
|
||||
owner: TableDetail['owner'],
|
||||
tier: TableDetail['tier']
|
||||
) => Promise<void>;
|
||||
};
|
||||
|
||||
const ManageTab: FunctionComponent<Props> = ({
|
||||
@ -37,6 +41,10 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
onSave,
|
||||
}: Props) => {
|
||||
const { data } = cardData;
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [status, setStatus] = useState<'initial' | 'waiting' | 'success'>(
|
||||
'initial'
|
||||
);
|
||||
const [activeTier, setActiveTier] = useState(currentTier);
|
||||
const [listVisible, setListVisible] = useState(false);
|
||||
const [listOwners] = useState(() => {
|
||||
@ -81,6 +89,8 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
setLoading(true);
|
||||
setStatus('waiting');
|
||||
// Save API call goes here...
|
||||
const newOwner: TableDetail['owner'] =
|
||||
owner !== currentUser
|
||||
@ -90,7 +100,10 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
}
|
||||
: undefined;
|
||||
const newTier = activeTier !== currentTier ? activeTier : undefined;
|
||||
onSave(newOwner, newTier);
|
||||
onSave(newOwner, newTier).catch(() => {
|
||||
setStatus('initial');
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
@ -106,6 +119,18 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
setOwner(currentUser);
|
||||
}, [currentUser]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 1000);
|
||||
if (status === 'waiting') {
|
||||
setStatus('success');
|
||||
setTimeout(() => {
|
||||
setStatus('initial');
|
||||
}, 3000);
|
||||
}
|
||||
}, [currentTier, currentUser]);
|
||||
|
||||
return (
|
||||
<div className="tw-max-w-3xl tw-mx-auto">
|
||||
<div className="tw-mt-2 tw-mb-4 tw-pb-4 tw-border-b tw-border-separator">
|
||||
@ -154,13 +179,34 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
onClick={handleCancel}>
|
||||
Discard
|
||||
</Button>
|
||||
<Button
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={handleSave}>
|
||||
Save
|
||||
</Button>
|
||||
{loading ? (
|
||||
<Button
|
||||
disabled
|
||||
className="tw-w-16 tw-h-10 disabled:tw-opacity-100"
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="contained">
|
||||
<Loader size="small" type="white" />
|
||||
</Button>
|
||||
) : status === 'success' ? (
|
||||
<Button
|
||||
disabled
|
||||
className="tw-w-16 tw-h-10 disabled:tw-opacity-100"
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="contained">
|
||||
<i aria-hidden="true" className="fa fa-check" />
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
className="tw-w-16 tw-h-10"
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={handleSave}>
|
||||
Save
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -223,31 +223,38 @@ const MyDataDetailsPage = () => {
|
||||
const onSettingsUpdate = (
|
||||
newOwner?: TableDetail['owner'],
|
||||
newTier?: TableDetail['tier']
|
||||
) => {
|
||||
if (newOwner || newTier) {
|
||||
const tierTag: TableDetail['tags'] = newTier
|
||||
? [
|
||||
...getTagsWithoutTier(tableDetails.tags),
|
||||
{ tagFQN: newTier, labelType: 'Manual', state: 'Confirmed' },
|
||||
]
|
||||
: tableDetails.tags;
|
||||
const updatedTableDetails = {
|
||||
...tableDetails,
|
||||
owner: newOwner
|
||||
? {
|
||||
...tableDetails.owner,
|
||||
...newOwner,
|
||||
}
|
||||
: tableDetails.owner,
|
||||
// tier: newTier || tableDetails.tier,
|
||||
tags: tierTag,
|
||||
};
|
||||
saveUpdatedTableData(updatedTableDetails).then((res) => {
|
||||
setTableDetails(res.data);
|
||||
setOwner(res.data.owner);
|
||||
setTier(getTierFromTableTags(res.data.tags));
|
||||
});
|
||||
}
|
||||
): Promise<void> => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (newOwner || newTier) {
|
||||
const tierTag: TableDetail['tags'] = newTier
|
||||
? [
|
||||
...getTagsWithoutTier(tableDetails.tags),
|
||||
{ tagFQN: newTier, labelType: 'Manual', state: 'Confirmed' },
|
||||
]
|
||||
: tableDetails.tags;
|
||||
const updatedTableDetails = {
|
||||
...tableDetails,
|
||||
owner: newOwner
|
||||
? {
|
||||
...tableDetails.owner,
|
||||
...newOwner,
|
||||
}
|
||||
: tableDetails.owner,
|
||||
// tier: newTier || tableDetails.tier,
|
||||
tags: tierTag,
|
||||
};
|
||||
saveUpdatedTableData(updatedTableDetails)
|
||||
.then((res) => {
|
||||
setTableDetails(res.data);
|
||||
setOwner(res.data.owner);
|
||||
setTier(getTierFromTableTags(res.data.tags));
|
||||
resolve();
|
||||
})
|
||||
.catch(() => reject());
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onSuggest = (updatedHTML: string) => {
|
||||
|
||||
@ -67,10 +67,6 @@ module.exports = {
|
||||
search: '#D5D6D9',
|
||||
},
|
||||
colors: {
|
||||
success: success,
|
||||
error: error,
|
||||
warning: warning,
|
||||
info: info,
|
||||
'grey-body': textBody,
|
||||
'grey-muted': textMuted,
|
||||
'grey-muted-lite': textMutedLite,
|
||||
@ -83,6 +79,10 @@ module.exports = {
|
||||
'body-main': bodyBG,
|
||||
'body-hover': bodyHoverBG,
|
||||
tag: tagBG,
|
||||
success: success,
|
||||
error: error,
|
||||
warning: warning,
|
||||
info: info,
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', ...defaultTheme.fontFamily.sans],
|
||||
@ -117,6 +117,7 @@ module.exports = {
|
||||
borderStyle: ['hover'],
|
||||
borderWidth: ['hover'],
|
||||
display: ['group-hover'],
|
||||
opacity: ['disabled'],
|
||||
},
|
||||
},
|
||||
plugins: [require('@tailwindcss/custom-forms')],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user