mirror of
				https://github.com/ClusterCockpit/cc-backend
				synced 2025-10-30 15:45:05 +01:00 
			
		
		
		
	adapt and improve svelte taglist component
This commit is contained in:
		| @@ -2,49 +2,142 @@ | ||||
|     @component Tag List Svelte Component. Displays All Tags, Allows deletion. | ||||
|  | ||||
|     Properties: | ||||
|     - `authlevel Int!`: Current Users Authority Level | ||||
|     - `tagmap Object!`: Map of Appwide Tags | ||||
|     - `username String!`: Users username. | ||||
|     - `isAdmin Bool!`: User has Admin Auth. | ||||
|     - `tagmap Object!`: Map of accessible, appwide tags. Prefiltered in backend. | ||||
|  --> | ||||
|  | ||||
| <script> | ||||
|   // import { Card, CardHeader, CardTitle } from "@sveltestrap/sveltestrap"; | ||||
|   import { | ||||
|     gql, | ||||
|     getContextClient, | ||||
|     mutationStore, | ||||
|   } from "@urql/svelte"; | ||||
|   import { | ||||
|     Badge, | ||||
|     InputGroup, | ||||
|     Icon, | ||||
|     Button, | ||||
|     Spinner, | ||||
|   } from "@sveltestrap/sveltestrap"; | ||||
|   import { | ||||
|     init, | ||||
|   } from "./generic/utils.js"; | ||||
|  | ||||
|   // export let authlevel; | ||||
|   export let username; | ||||
|   export let isAdmin; | ||||
|   export let tagmap; | ||||
|  | ||||
|   const {} = init(); | ||||
|   const client = getContextClient(); | ||||
|  | ||||
|   let pendingChange = "none"; | ||||
|  | ||||
|   const removeTagMutation = ({ tagIds }) => { | ||||
|     return mutationStore({ | ||||
|       client: client, | ||||
|       query: gql` | ||||
|         mutation ($job: ID!, $tagIds: [ID!]!) { | ||||
|           removeTag(tagIds: $tagIds) { | ||||
|             id | ||||
|             type | ||||
|             name | ||||
|             scope | ||||
|           } | ||||
|         } | ||||
|       `, | ||||
|       variables: { tagIds }, | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   function removeTag(tag, tagType) { | ||||
|     pendingChange = tagType; | ||||
|     removeTagMutation({tagIds: [tag.id] }).subscribe( | ||||
|       (res) => { | ||||
|         if (res.fetching === false && !res.error) { | ||||
|           tagmap = res.data.removeTag; | ||||
|           pendingChange = "none"; | ||||
|         } else if (res.fetching === false && res.error) { | ||||
|           throw res.error; | ||||
|         } | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   $: console.log(username, isAdmin) | ||||
|   $: console.log(pendingChange, tagmap) | ||||
| </script> | ||||
|  | ||||
| <div class="container"> | ||||
|     <div class="row justify-content-center"> | ||||
|         <div class="col-10"> | ||||
|         {#each Object.entries(tagmap) as [tagType, tagList]} | ||||
|             <div class="my-3 p-2 bg-secondary rounded text-white"> <!-- text-capitalize --> | ||||
|                 Tag Type: <b>{tagType}</b> | ||||
|                 <span style="float: right; padding-bottom: 0.4rem; padding-top: 0.4rem;" class="badge bg-light text-secondary"> | ||||
|                     {tagList.length} Tag{(tagList.length != 1)?'s':''} | ||||
|                 </span> | ||||
|             </div> | ||||
|             {#each tagList as tag (tag.id)} | ||||
|                 {#if tag.scope == "global"} | ||||
|                     <a class="btn btn-outline-secondary" href="/monitoring/jobs/?tag={tag.id}" role="button"> | ||||
|                         {tag.name} | ||||
|                         <span class="badge bg-primary mr-1">{tag.count} Job{(tag.count != 1)?'s':''}</span> | ||||
|                         <span style="background-color:#c85fc8;" class="badge text-dark">Global</span> | ||||
|                     </a> | ||||
|                 {:else if tag.scope == "admin"} | ||||
|                     <a class="btn btn-outline-secondary" href="/monitoring/jobs/?tag={tag.id}" role="button"> | ||||
|                         {tag.name} | ||||
|                         <span class="badge bg-primary mr-1">{tag.count} Job{(tag.count != 1)?'s':''}</span> | ||||
|                         <span style="background-color:#19e5e6;" class="badge text-dark">Admin</span> | ||||
|                     </a> | ||||
|                 {:else} | ||||
|                     <a class="btn btn-outline-secondary" href="/monitoring/jobs/?tag={tag.id}" role="button"> | ||||
|                         {tag.name} | ||||
|                         <span class="badge bg-primary mr-1">{tag.count} Job{(tag.count != 1)?'s':''}</span> | ||||
|                         <span class="badge bg-warning text-dark">Private</span> | ||||
|                     </a> | ||||
|                 {/if} | ||||
|             {/each} | ||||
|         {/each} | ||||
|   <div class="row justify-content-center"> | ||||
|     <div class="col-10"> | ||||
|       {#each Object.entries(tagmap) as [tagType, tagList]} | ||||
|         <div class="my-3 p-2 bg-secondary rounded text-white"> <!-- text-capitalize --> | ||||
|           Tag Type: <b>{tagType}</b> | ||||
|           {#if pendingChange === tagType} | ||||
|             <Spinner size="sm" secondary /> | ||||
|           {/if} | ||||
|           <span style="float: right; padding-bottom: 0.4rem; padding-top: 0.4rem;" class="badge bg-light text-secondary"> | ||||
|             {tagList.length} Tag{(tagList.length != 1)?'s':''} | ||||
|           </span> | ||||
|         </div> | ||||
|         <div class="d-inline-flex flex-wrap"> | ||||
|           {#each tagList as tag (tag.id)} | ||||
|             {#if tag.scope == "global"} | ||||
|               <InputGroup class="w-auto flex-nowrap" style="margin-right: 0.5rem; margin-bottom: 0.5rem;"> | ||||
|                 <Button outline color="secondary" href="/monitoring/jobs/?tag={tag.id}" target="_blank"> | ||||
|                   <Badge color="light" style="font-size:medium;" border>{tag.name}</Badge> :  | ||||
|                   <Badge color="primary" pill>{tag.count} Job{(tag.count != 1)?'s':''}</Badge> | ||||
|                   <Badge style="background-color:#c85fc8 !important;" pill>Global</Badge> | ||||
|                 </Button> | ||||
|                 {#if isAdmin} | ||||
|                   <Button | ||||
|                     size="sm" | ||||
|                     color="danger" | ||||
|                     on:click={() => removeTag(tag, tagType)} | ||||
|                   > | ||||
|                     <Icon name="x" /> | ||||
|                   </Button> | ||||
|                 {/if} | ||||
|               </InputGroup> | ||||
|             {:else if tag.scope == "admin"} | ||||
|               <InputGroup class="w-auto flex-nowrap" style="margin-right: 0.5rem; margin-bottom: 0.5rem;"> | ||||
|                 <Button outline color="secondary" href="/monitoring/jobs/?tag={tag.id}" target="_blank"> | ||||
|                   <Badge color="light" style="font-size:medium;" border>{tag.name}</Badge> :  | ||||
|                   <Badge color="primary" pill>{tag.count} Job{(tag.count != 1)?'s':''}</Badge> | ||||
|                   <Badge style="background-color:#19e5e6 !important;" pill>Admin</Badge> | ||||
|                 </Button> | ||||
|                 {#if isAdmin} | ||||
|                   <Button | ||||
|                     size="sm" | ||||
|                     color="danger" | ||||
|                     on:click={() => removeTag(tag, tagType)} | ||||
|                   > | ||||
|                     <Icon name="x" /> | ||||
|                   </Button> | ||||
|                 {/if} | ||||
|               </InputGroup> | ||||
|             {:else} | ||||
|               <InputGroup class="w-auto flex-nowrap" style="margin-right: 0.5rem; margin-bottom: 0.5rem;"> | ||||
|                 <Button outline color="secondary" href="/monitoring/jobs/?tag={tag.id}" target="_blank"> | ||||
|                   <Badge color="light" style="font-size:medium;" border>{tag.name}</Badge> :  | ||||
|                   <Badge color="primary" pill>{tag.count} Job{(tag.count != 1)?'s':''}</Badge> | ||||
|                   <Badge color="warning" pill>Private</Badge> | ||||
|                 </Button> | ||||
|                 {#if tag.scope == username} | ||||
|                   <Button | ||||
|                     size="sm" | ||||
|                     color="danger" | ||||
|                     on:click={() => removeTag(tag, tagType)} | ||||
|                   > | ||||
|                     <Icon name="x" /> | ||||
|                   </Button> | ||||
|                 {/if} | ||||
|               </InputGroup> | ||||
|             {/if} | ||||
|           {/each} | ||||
|         </div> | ||||
|       {/each} | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
| @@ -4,9 +4,13 @@ import Tags from './Tags.root.svelte' | ||||
| new Tags({ | ||||
|     target: document.getElementById('svelte-app'), | ||||
|     props: { | ||||
|         // authlevel: authlevel, | ||||
|         username: username, | ||||
|         isAdmin: isAdmin, | ||||
|         tagmap: tagmap, | ||||
|     } | ||||
|     }, | ||||
|     context: new Map([ | ||||
|         ['cc-config', clusterCockpitConfig] | ||||
|     ]) | ||||
| }) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -6,8 +6,10 @@ | ||||
| {{end}} | ||||
| {{define "javascript"}} | ||||
|     <script> | ||||
|         const authlevel = {{ .User.GetAuthLevel }}; | ||||
|         const username = {{ .User.Username }}; | ||||
|         const isAdmin = {{ .User.HasRole .Roles.admin }}; | ||||
|         const tagmap = {{ .Infos.tagmap }}; | ||||
|         const clusterCockpitConfig = {{ .Config }}; | ||||
|     </script> | ||||
|     <script src='/build/taglist.js'></script> | ||||
| {{end}} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user