component.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import { LitElement, html, css } from 'lit'
  2. import treeQuery from './tree.graphql'
  3. /**
  4. * Block Index
  5. */
  6. export class BlockIndexElement extends LitElement {
  7. static get styles() {
  8. return css`
  9. :host {
  10. display: block;
  11. margin-bottom: 16px;
  12. }
  13. ul {
  14. padding: 0;
  15. margin: 0;
  16. list-style: none;
  17. display: grid;
  18. grid-auto-flow: row;
  19. grid-template-columns: repeat(1, minmax(0, 1fr));
  20. gap: 0.5rem;
  21. }
  22. @media (min-width: 1024px) {
  23. ul {
  24. grid-template-columns: repeat(2, minmax(0, 1fr));
  25. }
  26. }
  27. li {
  28. background-color: #fafafa;
  29. background-image: linear-gradient(to bottom,#fff,#fafafa);
  30. border-right: 1px solid rgba(0,0,0,.05);
  31. border-bottom: 1px solid rgba(0,0,0,.05);
  32. border-left: 5px solid rgba(0,0,0,.1);
  33. box-shadow: 0 3px 8px 0 rgba(116,129,141,.1);
  34. padding: 0;
  35. border-radius: 5px;
  36. font-weight: 500;
  37. display: flex;
  38. align-items: stretch;
  39. justify-content: stretch;
  40. }
  41. :host-context(body.body--dark) li {
  42. background-color: #222;
  43. background-image: linear-gradient(to bottom,#161b22, #0d1117);
  44. border-right: 1px solid rgba(0,0,0,.5);
  45. border-bottom: 1px solid rgba(0,0,0,.5);
  46. border-left: 5px solid rgba(255,255,255,.2);
  47. box-shadow: 0 3px 8px 0 rgba(0,0,0,.25);
  48. }
  49. li:hover {
  50. background-color: var(--q-primary);
  51. background-image: linear-gradient(to bottom,#fff,rgba(255,255,255,.95));
  52. border-left-color: var(--q-primary);
  53. cursor: pointer;
  54. }
  55. :host-context(body.body--dark) li:hover {
  56. background-image: linear-gradient(to bottom,#1e232a, #161b22);
  57. border-left-color: var(--q-primary);
  58. }
  59. li a {
  60. display: flex;
  61. color: var(--q-primary);
  62. padding: 1rem;
  63. text-decoration: none;
  64. flex: 1;
  65. flex-direction: column;
  66. justify-content: center;
  67. position: relative;
  68. }
  69. li a > span {
  70. display: block;
  71. color: #666;
  72. font-size: .8em;
  73. font-weight: normal;
  74. pointer-events: none;
  75. }
  76. li a > svg {
  77. width: 32px;
  78. position: absolute;
  79. right: 16px;
  80. pointer-events: none;
  81. }
  82. li a > svg path {
  83. fill: rgba(0,0,0,.2);
  84. }
  85. :host-context(body.body--dark) li a > svg path {
  86. fill: rgba(255,255,255,.2);
  87. }
  88. li:hover a > svg path, :host-context(body.body--dark) li:hover a > svg path {
  89. fill: color-mix(in srgb, currentColor 50%, transparent);
  90. }
  91. .no-links {
  92. color: var(--q-negative);
  93. border: 1px dashed color-mix(in srgb, currentColor 50%, transparent);
  94. border-radius: 5px;
  95. padding: 1rem;
  96. }
  97. `
  98. }
  99. static get properties() {
  100. return {
  101. /**
  102. * The base path to fetch pages from
  103. * @type {string}
  104. */
  105. path: { type: String },
  106. /**
  107. * A comma-separated list of tags to filter with
  108. * @type {string}
  109. */
  110. tags: { type: String },
  111. /**
  112. * The maximum number of items to fetch
  113. * @type {number}
  114. */
  115. limit: { type: Number },
  116. /**
  117. * Ordering (createdAt, fileName, title, updatedAt)
  118. * @type {string}
  119. */
  120. orderBy: { type: String },
  121. /**
  122. * Ordering direction (asc, desc)
  123. * @type {string}
  124. */
  125. orderByDirection: { type: String },
  126. /**
  127. * Maximum folder depth to fetch
  128. * @type {number}
  129. */
  130. depth: { type: Number },
  131. /**
  132. * A fallback message if no results are returned
  133. * @type {string}
  134. */
  135. noResultMsg: { type: String },
  136. // Internal Properties
  137. _loading: { state: true },
  138. _pages: { state: true }
  139. }
  140. }
  141. constructor() {
  142. super()
  143. this._loading = true
  144. this._pages = []
  145. this.path = ''
  146. this.tags = ''
  147. this.limit = 10
  148. this.orderBy = 'title'
  149. this.orderByDirection = 'asc'
  150. this.depth = 0
  151. this.noResultMsg = 'No pages matching your query.'
  152. }
  153. async connectedCallback() {
  154. super.connectedCallback()
  155. try {
  156. const resp = await APOLLO_CLIENT.query({
  157. query: treeQuery,
  158. variables: {
  159. siteId: WIKI_STATE.site.id,
  160. locale: WIKI_STATE.page.locale,
  161. parentPath: this.path,
  162. limit: this.limit,
  163. orderBy: this.orderBy,
  164. orderByDirection: this.orderByDirection,
  165. depth: this.depth,
  166. ...this.tags && { tags: this.tags.split(',').map(t => t.trim()).filter(t => t) },
  167. }
  168. })
  169. this._pages = resp.data.tree.map(p => ({
  170. ...p,
  171. href: p.folderPath ? `/${p.folderPath}/${p.fileName}` : `/${p.fileName}`
  172. }))
  173. } catch (err) {
  174. console.warn(err)
  175. }
  176. this._loading = false
  177. }
  178. render() {
  179. return this._pages.length > 0 || this._loading ? html`
  180. <ul>
  181. ${this._pages.map(p =>
  182. html`<li>
  183. <a href="${p.href}" @click="${this._navigate}">
  184. ${p.title}
  185. ${p.description ? html`<span>${p.description}</span>` : null}
  186. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px">
  187. <path d="M 24 4 C 12.972292 4 4 12.972292 4 24 C 4 32.465211 9.2720863 39.722981 16.724609 42.634766 A 1.50015 1.50015 0 1 0 17.816406 39.841797 C 11.48893 37.369581 7 31.220789 7 24 C 7 14.593708 14.593708 7 24 7 A 1.50015 1.50015 0 1 0 24 4 z M 32.734375 6.1816406 A 1.50015 1.50015 0 0 0 32.033203 9.0136719 C 37.368997 11.880008 41 17.504745 41 24 C 41 33.406292 33.406292 41 24 41 A 1.50015 1.50015 0 1 0 24 44 C 35.027708 44 44 35.027708 44 24 C 44 16.385255 39.733331 9.7447579 33.453125 6.3710938 A 1.50015 1.50015 0 0 0 32.734375 6.1816406 z M 25.484375 16.484375 A 1.50015 1.50015 0 0 0 24.439453 19.060547 L 27.878906 22.5 L 16.5 22.5 A 1.50015 1.50015 0 1 0 16.5 25.5 L 27.878906 25.5 L 24.439453 28.939453 A 1.50015 1.50015 0 1 0 26.560547 31.060547 L 32.560547 25.060547 A 1.50015 1.50015 0 0 0 32.560547 22.939453 L 26.560547 16.939453 A 1.50015 1.50015 0 0 0 25.484375 16.484375 z"/>
  188. </svg>
  189. </a>
  190. </li>`
  191. )}
  192. </ul>
  193. ` : html`
  194. <div class="no-links">${this.noResultMsg}</div>
  195. `
  196. }
  197. _navigate (e) {
  198. e.preventDefault()
  199. WIKI_ROUTER.push(e.target.getAttribute('href'))
  200. }
  201. // createRenderRoot() {
  202. // return this;
  203. // }
  204. }
  205. window.customElements.define('block-index', BlockIndexElement)