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