mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-10-31 02:29:03 +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
	 darth-coder00
						darth-coder00